Vous êtes sur la page 1sur 562

Instalando Apache 2.2.17 Qu es un servidor WEB?

Podramos definir un servidor WEB como una aplicacin que permite acceder a los recursos contenidos en algunos de los directorios del ordenador que la alberga a usuarios remotos que realizan sus peticiones mediante el protocolo HTTP. Por tanto, instalar un servidor web no es otra cosa que instalar y configurar un programa en una unidad o directorio de un ordenador cualquiera.

Qu es Apache?
Bajo este nombre suele hacerse referencia a Apache Software Foundation, organizacin norteamericana que se autodefine con el objetivo de ... facilitar ayuda organizativa, legal y financiera para los proyectos de desarrollo de software tipo Open Source (cdigo abierto). Uno de los proyectos ms populares de Apache es el desarrollo y suministro -de forma gratuita y libre- de un software de servidor HTTP, conocido tambin como el servidor Apache.

La corta historia de Apache


Apache Software Foundation tiene su origen en febrero de 1995. Hasta ese momento el software ms popular de servidores de HTTP era el desarrollado por Rob McCool, miembro del Centro Nacional para Aplicaciones de Super computacin (NCSA), de la Universidad de Illinois. El desarrollo de aquel primitivo software de servidor de NCSA (software de dominio pblico y cdigo abierto) tuvo algunos problemas a mediados del ao 1994. Esta circunstancia oblig a que muchos de los webmasters que utilizaban aquella aplicacin tuvieran que desarrollar sus propias extensiones y corregir de forma individual los fallos de funcionamiento de la aplicacin original. Un pequeo grupo de aquellos webmasters entr en contacto va e-mail con el objetivo de coordinar y conjuntar sus trabajos de correccin y mejora de la aplicacin original de NCSA. Fueron Brian Behlendorf y Cliff Skolnick quienes a travs de una lista de correo coordinaron el trabajo y lograron establecer un espacio compartido de libre acceso para quienes participaran en el proyecto en un ordenador instalado en California. En febrero de 1995, ocho colaboradores del primitivo proyecto decidieron aunar sus esfuerzos de forma organizada y fundaron lo que fue conocido como Grupo Apache. Usando como base el HTTPD 1.3 de NCSA y aplicando los patchs desarrollados hasta ese momento, lanzaron la primera versin oficial (versin 0.6.2) del software de servidor de Apache en abril de 1995. Aquella primera versin entr en un rpido e intenso proceso de mejoras y alcanz una gran implantacin como software de servidor inicialmente era slo para UNIX para diferentes plataformas, una de las cuales es la versin para Windows que nosotros utilizaremos y que frente a otras alternativas de servidor HTTP tiene las ventajas de ser gratuita y muy eficaz.

Instalacin de Apache
En el sitio de descargas de Apache o en el mirror espaol puedes encontrar un fichero llamado httpd-2.2.17-win32-x86openssl-0.9.8o.msi (es la versin que he incluido en el autoinstalador) o parecido. Digo parecido porque las versiones van evolucionando y en esas direcciones tienes la ltima de las versiones y es posible que cuando accedas ya se haya actualizado. En cualquier caso si tienes inters por una versin especfica de Apache puedes encontrarla en esta especie de repositorio histrico. Una vez descargado el programa instalador bastar con que hagas doble clic sobre su icono para que te aparezca una pantalla como esta:

Si en vez de esta pantalla apareciera un mensaje de error, es muy probable que se deba a que no tienes instalada la aplicacinWindows Installer Redistributable necesaria para ejecutar los ficheros con extensin .msi. Las versiones modernas de Windows a partir de Windows98 la tienen incorporada, pero si por cualquier circunstancia usando Windows98 no dispones de ella, puedes descargarla desde este enlace. Al pulsar Next en la ventana anterior se llega a esta otra en la que es preciso tener seleccionada la opcin I accept the terms in the license agreement para que se active el botn Next y poder continuar la instalacin.

Al llegar a esta otra ventana las anteriores solo requieren ir pulsando en el botn Next es imprescindible rellenar los camposNetwork Domain, Server Name y Administrator's e-mail adress.

Como Network Domain y como Administrator's e-mail adress puedes poner nombres cualesquiera siempre que no contengan espacios ni caracteres especiales y en el caso de la direccin e-mail sta debe contener el smbolo @. Como Server Name escribelocalhost. La instalacin recomendada de Apache For All Users, on port 80, as a Service contempla el uso del servidor como un servidor de red de rea local accesible desde el resto de los ordenadores de esa red. Es lgico que en esas circunstancias el servidor se configure conautoarranque y que se inicie automticamente en el momento en que se arranca el ordenador Si piensas utilizar el servidor para probar y depurar tus propios scripts PHP seguramente vas a ocupar en ello slo una pequea parte del tiempo de uso del ordenador, por lo que parece ser ms eficaz la opcin de arrancarlo nicamente cuando sea necesario y, de esa forma, ahorrar esos recursos del sistema que podran ralentizar el uso de otros programas cuando no necesites usar el servidor. Por esa razn te sugiero elegir la opcin only for the Current User, on port 8080, when started manually y pulsar de nuevo Next. En la pantalla que aparece inmediatamente despus de la anterior se permite elegir el modo de instalacin: Typical Custom. Elige la opcin Custom y pulsa nuevamente sobre Next.

Te aparecer esta nueva pantalla en la que el instalador te indica el directorio por defecto en el que pretende instalar el servidor Apache.

En este caso aunque no es necesario hacerlo te sugiero pulsar sobre Change y cambiarlo nicamente por razones de comodidad. La idea es agrupar todos los programas relacionados con PHP en un solo directorio (es la razn de definir c:/ServidoresLocales para ese fn) y dentro de l asignar un nombre fcilmente identificable para cada uno de los programas (Apache, en este caso). Despus del Change de la ventana anterior aparecer esta otra. Ponla con la misma configuracin que aparece en la imagen inferior, es decir, con Look in : (ServidoresLocales) y deja como Folder name: C:/ServidoresLocales/Apache/

Como podrs leer en la propia pantalla de instalacin, es muy importante poner la barra invertida (\) detrs del nombre de la unidad al indicar el Folder name. No te olvides de hacerlo.

Una vez hayas pulsado OK volver a aparecer la ventana que permite cambiar el directorio de instalacin. Comprueba que ahora digaInstall to: C:/ServidoresLocales/Apache/ y pulsa Next en esa ventana y en las siguientes. Aparecer una ltima ventana donde dice Installation Wizard Completed y una vez que hayas pulsado el botn Finish la instalacin de Apache habr terminado.

Desactivar el monitor

Durante el proceso anterior se instala automticamente el icono del monitor de servicio en la barra de tareas tal como puedes ver en esta imagen. Puedes cerrarlo pulsando con el botn derecho del ratn sobre el icono y eligiendo la opcin exit. Durante el proceso de instalacin de Apache se incluye en el men iniciode Windows un enlace al Monitor de Apache. Ello significa que cada vez que reinicies el equipo se instalar en la barra de tareas el icono del monitor. Para desactivarlo de forma definitiva bastar con eliminar tal acceso directo de la forma que puedes ver en la imagen inferior.

Arrancar Apache
Contemplando la opcin de arranque manual, cada vez que quieras poner en marcha el servidor tendrs que acceder al icono Start Apache in console, que podrs encontrar en la localizacin de la imagen que ves aqu debajo.

Cuando se inicia Apache se abre siempre la consola de MS-DOS. En los primeros arranques es posible que aparezca en ella un mensaje como el que ests viendo en la imagen inferior.

Este mensaje de advertencia no afecta a las pruebas ni al funcionamiento de servidor. No obstante, en el esquema del proceso de configuracin que tienes un poco ms abajo puedes ver cmo hacer una modificacin en la configuracin del servidor que evita su aparicin. Otra forma de efectuar el arranque sera ejecutar directamente el programa httpd.exe que se encuentra en:C:/ServidoresLocales/Apache/bin. Haciendo doble clic sobre su icono o tecleando el comando desde el smbolo del sistema de la consola de Windows aparecer una ventana de MS-DOS tal como la que ves en la imagen de arriba. No la cierres nunca! Si lo haces slo conseguiras apagar el servidor y adems lo haras de una forma muy poco ortodoxa. Si te resulta incmoda minimzala pero no la cierres.

Una pgina de prueba


Con el servidor arrancado y funcionando, bastar con que abras tu navegador y escribas en la barra de direcciones una de las siguientes: http://localhost:8080 o http://127.0.0.1:8080. para que, si la instalacin de Apache es correcta, se abra una pgina similar a la ves en la imagen. S eso ocurre, es la prueba de que el servidor est funcionando correctamente.

Pgina de prueba del servidor Apache. Observa la direccin:http://localhost:8080 Si te ests preguntado por qu esas direcciones localhost 127.0.0.1 o por qu no hemos escrito el nombre de ninguna de pgina web, ten un poco de paciencia! Trataremos de ello cuando configuremos Apache.

Apagar Apache
Aunque se puede desconectar cerrando la ventana de MS-DOS, el mtodo correcto es: establecer esa ventana como ventana activa, pulsar las teclas Ctrl+C y esperar unos pocos segundos. Transcurrido ese tiempo la ventana MS-DOS se cerrar automticamente y se habrapagado Apache.

Desinstalacin de Apache
El servidor Apache se desinstala como cualquier otro programa de Windows. Bastar con acceder a Paneles de control, opcin deAgregar o quitar programas elegirlo en la lista de programas instalados y desinstalarlo. Antes de ejecutar ese proceso es necesario que el servidor est apagado y saber que quedarn algunos restos de la instalacin que si fuera necesario habra que eliminar manualmente. El desinstalador de Apache no eliminar ni el directorio raz C:/ServidoresLocales/Apache/ ni los subdirectorios conf y htdocs del mismo. La razn es la seguridad. El directorio conf contiene los archivos de configuracin del servidor en pginas posteriores veremos que hay que modificar sus valores por defecto y al no eliminarlos nos estar dando la opcin de poder reutilizarlos (sin tener que empezar de cero) en futuras instalaciones. Lo mismo ocurre con htdocs. En ese directorio ser donde se almacenen los documentos que vayamos creando pginas web, imgenes, etctera y, como es lgico, un error en el proceso de desinstalacin podra provocar su prdida. Esa es la razn de que se conserven. Por idnticas razones, si al reinstalar Apache ya existieran esos directorios no seran sobrescritos mantenindose las configuraciones y documentos de la versin anterior.

Configuracin de Apache
El correcto funcionamiento del servidor Apache requiere efectuar una serie de modificaciones en su fichero de configuracin (httpd.conf). Las modificaciones propuestas y su justificacin son las que se resumen en la siguiente tabla. httpd.conf
(est en C:/ServidoresLocales/Apache/conf)

Fichero inicial Guardar como (*) Guardar como

httpd.orig httpd.conf
Cambios Donde dice:

Guardaremos el fichero modificado con dos nombres distintos. Uno de ellos para hacer la primera prueba del servidor (httpd.conf) y el otro (httpd.orig) para utilizarlo como base de las modificaciones posteriores.

Modificaciones en el fichero inicial Lnea Justificacin Mediante esta modificacin evitaremos que el servidor escuche el puerto 8080 y le obligaremos a utilizar el puerto por defecto (80). Observa que en la pgina de prueba anterior habamos escrito:http://localhost:8080 (para utilizar el puerto 8080 que era el que escuchaba el servidor) y una vez hecha esta modificacin bastar poner: http://localhost ya que 80 es el puerto por defecto y no es necesario especificarlo. Al descomentar (quitar #) esta lnea evitaremos el mensaje de error que apareca en la consola de MS-DOS al realizar las pruebas anteriores. Una vez omitamos el valor :8080 ya no ser preciso especificar el puerto de acceso al servidor al pedir las pginas desde el navegador. Las peticiones se canalizarn por el puerto por defecto, el puerto 80.

Listen 8080 46
cambiar por:

Listen 80
Donde dice:

172

#ServerName localhost:8080
cambiar por:

ServerName localhost

Nombres de dominio en un servidor local


Est opcin no es necesaria pero es posible que te apetezca tener tu propio dominio local para poner utilizar una direccin personalizada, alternativa a localhost, como nombre de dominio. Si utilizas Windows98 encontrars un fichero con el nombre hosts o hosts.sam en el directorio Windows. Si tu sistema operativo esW2000, NT XP , Vista o Windows 7 tendrs que buscar ese fichero en un subdirectorio, del directorio de sistema, llamado\system32\drivers\etc\ Al editar ese fichero hosts.sam o hosts- encontrars algo similar a esto:

# For example: # # 102.54.94.97 # 38.25.63.10 127.0.0.1

rhino.acme.com x.acme.com

# source server # x client host

localhost

Si aades una lnea como la sealada en rojo la IP 127.0.0.1 ha de mantenerse y pones cualquier nombre de dominio (mispruebas.as) en el caso del ejemplo

# For example: # # 102.54.94.97 # 38.25.63.10 127.0.0.1 127.0.0.1

rhino.acme.com x.acme.com

# source server # x client host

localhost mispruebas.as

bastar con que guardes el fichero con los cambios con el nombre hosts (sin ninguna extensin y en el mismo directorio). A partir de ese momento, ya podrs escribir en el navegador -con Apache en marcha- cualquiera de estas direcciones: http://localhost o http://127.0.0.1 ohttp://mispruebas.as

Nombres de dominio en redes locales


Cuando se utiliza un servidor a travs de una red de rea local, lo habitual es acceder a l escribiendo como direccin la IP de ordenador en el que se encuentra instalado el servidor. Mediante un proceso similar al descrito ms arriba, se puede modificar el fichero HOSTS de uno (o varios) de los equipos de la red aadiendo una lnea con el nombre del dominio ficticio precedida de la direccin IP del servidor. Si la IP del servidor local fuera 168.0.12.234, al incluir en el fichero hosts una lnea diciendo: 168.0.12.234 mispruebas.as podramos acceder a l tanto mediante: http://168.0.12.234 como a travs de: http://mispruebas.as

Cuidado! Esta versin de Apache de 32 bits funciona sin problema aparente en Windows XP, Vista y W 7 tanto en sus versiones de 32 bits como en las de 64 bits.

Instalacin de PHP 5.3.8


Qu es PHP y que requiere para ser usado
El lenguaje PHP acrnimo de Hypertext Pre Processor suele definirse como: interpretado y de alto nivel. Es un lenguaje de script cuyo cdigo va insertado dentro de las pginas HTML y es interpretado, siempre, en el servidor. Se trata un lenguaje de estilo clsico, multiplataforma y cercano en su sintaxis a C++. Creado por Rasmus Lerdorf en 1994; siendo su labor continuada por diversos desarrolladores, entre ellos Andi Gutmans y Zeev Suraski que fueron quienes propiciaron la aparicin de la versin PHP 3.0. Actualmente la implementacin principal de PHP (el estndar defacto), es producida por The PHP Group y se publica bajo la PHP License, a la que la Free Software Foundation considera una licencia desoftware libre. Para trabajar con PHP es necesario tener instalado un servidor HTTP en nuestro caso, Apache para Windows y configurarlo de tal manera que sea posible la interaccin entre ambas aplicaciones.

Instalando el PHP

En el sitio oficial de PHP podrs encontrar, bajo el epgrafe VC9 x86 Thread Safe, un fichero llamado php-5.3.8-Win32-VC9-x86.zip. Igual que ocurra en el caso de Apache las versiones pueden haber evolucionado. Por si tienes capricho por una versin concreta aqu tienes el museo del PHP dnde puedes encontrar cualquiera de las versiones que ya han pasado a formar parte de la historia. Si tienes instalado Winzip, al hacer doble clic sobre el icono se te abrir la ventana de este descompresor y al pulsar sobre el icono Extract se te abrir una ventana como la que aparece en la imagen. Si has seguido los pasos indicados en la pgina anterior para la instalacin del servidor Apache, tendrs en tu ordenador un directorio llamado C:\ServidoresLocales. Selecciona como directorio de descompresin C:/ServidoresLocales/php53 tal como ests viendo en la figura y realiza la extraccin.

Una vez concluida la descompresin se habr creado el directorio C:/ServidoresLocales/php53 que contendr a su vez una serie de subdirectorios necesarios para el correcto funcionamiento de PHP. El proceso de instalacin de PHP habr terminado. Solo resta la configuracin de Apache y PHP para poder empezar a utilizarlo. Esto ser lo que veremos en la pgina siguiente.

Podemos probar ahora PHP?


Si ya has realizado el proceso de instalacin tal como lo hemos descrito en los prrafos anteriores, puede que te preguntes si como hemos hecho al instalar Apache es posible hacer ahora una prueba de su funcionamiento. La respuesta es NO. Analiza con un poco de detenimiento el proceso que hemos seguido y observars que no hemos hecho una instalacin sino que nos hemos limitado a descomprimir una serie de ficheros colocndolos en un directorio determinado. Lo hemos hecho as porque lo que acabamos de instalar no es una aplicacin que pueda funcionar de forma autnoma, sino elintrprete de un lenguaje de scripts del lado del servidor que requiere ser invocado por medio de un software de servidor. As que, antes de que pueda ser utilizado, tendremos que indicarle al servidor Apache el sitio dnde ha de buscarlo y cundo debe utilizarlo.

Configuracin de Apache 2.2.17 para PHP 5.3.8


Para facilitar las cosas
A lo largo de este proceso y en otros sucesivos vas a encontrar ficheros que tienen el mismo nombre y que se diferencian slo por la extensin. Sera una buena idea tener Windows configurado de forma que se visualicen siempre las extensiones de todos los tipos de ficheros. Si nunca has usado esa opcin de Windows bastar con que hagas doble clic en el icono Mi PC y vayas a la opcin Ver (en el caso deWindows2000, XP o Vista habrs de ir a la opcin Herramientas) de la ventana que se abre. Cuando se trate de Windows7 habrs de ir aPaneles de Control->Opciones de carpeta en el submen de esa opcin elige Opciones de Carpeta. Una vez en Opciones de Carpeta debes elegir la opcin Ver de la nueva ventana y buscar la lnea en la que dice Ocultar extensiones

para los tipos de archivos conocidos y,desmarcando su casilla de verificacin y pulsando sobre Aplicar y Aceptar ya podrs visualizar las extensiones de todos los ficheros.

Modificacin del fichero httpd.conf para configurar PHP


Tal como comentbamos en la pgina anterior la utilizacin de PHP requiere introducir algunos cambios en la configuracin de Apache. En el momento en el que se instala este servidor se crea automticamente en el subdirectorio C:/ServidoresLocales/Apache/conf unfichero llamado httpd.conf que contiene la configuracin por defecto del servidor Apache. Como recordars lo hemos modificado durante el proceso de instalacin para que el servidor utilice el puerto 80. Tendremos que hacer algunas modificaciones ms. Pero, como precaucin por si tenemos algn problema y necesitamos volver a utilizar el fichero de la configuracin por defecto, vamos a hacer una copia de seguridad. Abriremos el documento httpd.conf con un editor de textos cualquiera lo ms cmodo ser utilizar Notepad ++ u otro editor que seale los nmeros de lnea y con la opcin guardar comocrearemos una copia con el nombre httpd.orig

Cuidado! Si has utilizado el bloc de notas de Windows es probable que en el proceso anterior no te haya guardado comohttpd.orig sino como httpd.orig.txt. Comprueba los ficheros del directorio C:/ServidoresLocales/Apache/conf y si te ha ocurrido lo que comentamos tendrs que recurrir al conocido mtodo de pulsar sobre el icono del fichero con el botn derecho del ratn, elegir la opcin Cambiar nombre y quitar el .txt que aparece al final del nombre del archivo.

Una vez hecho esto ya podremos hacer las modificaciones con toda tranquilidad, as que volveremos a abrir el fichero httpd.conf para hacer los cinco cambios siguientes:

Fichero inicial Guardar como Lnea

httpd.conf httpd.conf
Cambios Donde dice:

No es necesario modificar el nombre de este fichero. Ya debemos de tener una copia previa llamada http.orig

Modificaciones en el fichero inicial Justificacin Hemos de indicar a Apache que cargue el mdulo que se encuentra en el sitio que indican la ruta y el nombre del fichero. Este mdulo especfico para Apache 2.2 (php5apache2_2.dll) es el que permite que el servidor Apache interacte con PHP 5.

129

(lnea en blanco)
cambiar por: Donde dice:

LoadModule php5_module C:/ServidoresLocales/php53/php5apache2_2.dll Options Indexes FollowSymLinks


cambiar por: Evita que se visualice la lista de ficheros contenidos en un directorio de servidor si se intenta acceder a una pgina inexistente

219

Options -Indexes FollowSymLinks MultiViews


Donde dice:

241

DirectoryIndex index.html
cambiar por:

Permite indicar que ficheros y en que orden han de buscarse cuando en la peticin se indique el nombre del directorio pero no se especifique ninguna pgina.

DirectoryIndex index.html index.htm index.php


Donde dice:

384

(lnea en blanco)
cambiar por:

AddType application/x-httpd-php .php


Donde dice:

Le indica a Apache que los nicos ficheros susceptibles de contener scripts que deban ser ejecutados por el intrprete de PHP son aquellos que tienen como extensin .php. Si un fichero con extensin distinta contuviera scripts PHP stos no seran ejecutados. La inclusin de la lnea PHPIniDir (una novedad respecto a versiones anteriores de Apache y PHP) permite indicar la ruta de acceso al fichero de configuracin de PHP (php.ini) En la pgina siguiente trataremos la configuracin de PHP.

385

#
sustituir por:

PHPIniDir "C:/ServidoresLocales/php53"

Una vez efectuados estos cambios ya podremos guardar el fichero, sin cambiar su nombre original httpd.conf, y tendremos lista la nueva configuracin de Apache. Solo nos falta reiniciar el servidor para que los cambios sean efectivos

Algunos detalles importantes sobre httpd.conf

La directiva de configuracin de Apache, DirectoryIndex, tiene particular inters para comodidad del usuario. A travs de ella le estaremos diciendo a Apache que cuando reciba una peticin dirigida a uno cualquiera de los directorios accesibles a travs de HTTP en la que no se especifique ningn nombre de pgina, debe comprobar si en ese directorio existe alguna pgina llamada index.html. En caso de que dicha pgina existiera la mostrara y en caso contrario volvera a comprobar para ver si existe alguna otra llamadaindex.htm (el segundo nombre de pgina contenido en esa lnea). Si tampoco se diera esa coincidencia continuar viendo si existe index.php. En el caso de que no encontrara ninguna que coincida con los nombres indicados en esta directiva dara un mensaje de error del tipo: File not found. Esta opcin de configuracin de Apache es la que nos permite escribir direcciones del estilo www.boe.es en las que sin especificar ningn nombre de pgina nos aparece en pantalla el mismo contenido que si hubiramos escrito: www.boe.es/index.php Si con la configuracin descrita en la tabla anterior intentamos acceder a la direccin: http://localhost/images/ nos aparecera un mensaje como este:

Esto ocurre como consecuencia de haber puesto el signo menos delante de Indexes (cuidado! debe ir pegado a Indexes sin ningn espacio intermedio) en la lnea Options -Indexes FollowSymLinks MultiViews. El subdirectorio images no contiene ficheros con nombre index.html, ni tampoco index.php ni index.htm (los especificados en la directiva DirectoryIndex) y el signo menos lo que hace es denegar el acceso (en el caso de no indicar el nombre de algn documento en la direccin) a los directorios que no los contengan. Si no hubiramos modificado esa directiva nos aparecera una lista con todos los ficheros contenidos en ese subdirectorio, tal como puedes ver en esta imagen.

La configuracin de Apache permite mltiples opciones y ofrece muchas posibilidades. Tantas, que justificaran todo un curso dedicado al estudio de este servidor y sus opciones de configuracin. No entraremos en ese mbito pero, aunque no vamos a modificarlos, es conveniente conocer algunos otros elementos importantes de httpd.conf. DocumentRoot "C:/ServidoresLocales/Apache/htdocs" Esta lnea que se ha incluido automticamente al hacer la instalacin indica la ruta y el nombre del directorio en el que,obligatoriamente, han de estar los documentos y los subdirectorios susceptibles de ser servidos a travs del protocolo HTTP. Cualquier documento que estuviera fuera de este directorio sera inaccesible, por lo tanto todos los documentos PHP que vayas creando debers guardarlos dentro de este directorio htdocs. Como es lgico, bastara cambiar esa lnea de la configuracin para utilizar como raz del servidor otro directorio cualquiera. ServerName localhost Esta otra lnea tambin contenida en httpd.conf es la que determina el nombre del servidor y a travs de ella se identifican las peticiones que el navegador realiza a ese servidor. Por esta razn, cuando probbamos la instalacin de Apache, escribamos como direccin http://localhost.

Configuracin de PHP 5.3.8 Un directorio importante


Antes de comenzar la configuracin de php es conveniente que creemos dentro de C:/ServidoresLocales/ un subdirectorio con nombre tmp que ser utilizado para contener las eventuales variables de sesin que fuera necesario manejar por parte de PHP y cuya ubicacin ha de ser especificada en la configuracin de este. No es preciso que utilicemos ni este nombre ni este directorio ni tampoco es necesario que se incluya en ningn directorio concreto del servidor. La eleccin del directorio ServidoresLocales obedece nicamente a la razn ya comentada de intentar incluir all todo lo relativo al PHP.

Configuracin de PHP
Con la configuracin de PHP ocurre lo mismo que en el caso de Apache. Tambin existen un montn de posibilidades de configuracin iremos viendo algunas de ellas a medida que vaya siendo necesario a travs de las cuales se puede modificar de forma sustancial el comportamiento de PHP. El elemento clave de la configuracin de PHP es un fichero denominado php.ini que debe estar contenido en el directorioC:\ServidoresLocales\php53 dado que fue esa la ubicacin que hemos incluido en la directiva PHPIniDir cuando configurbamos Apache en la pgina anterior.

Antes de empezar la configuracin


Si abrimos nuestro directorio: C:/ServidoresLocales/php53 encontraremos dentro de l tres ficheros que deberemos copiar a nuestro sistema tal como se indica en la siguiente tabla.
Ficheros originales S.O.

php5ts.dll
Directorio

libeay32.dll

ssleay32.dll

Copiar en el subdirectorio que se indica (dentro del que contiene el S.O.)

Windows98 W2000 Windows NT Windows XP Windows Vista W 7 32 bits W 7 64 bits

\system

\system32

\SysWOW64

Si ya tuviramos un fichero con ese nombre en el directorio de destino habramos de sobrescribirlo sustituyendo el preexistente por el que tenemos en C:/ServidoresLocales/php53. Con ello estaramos asegurndonos de que las versiones de estas libreras son las correspondientes a la versin de PHP que pretendemos utilizar.

Configuracin de PHP
En el directorio C:/ServidoresLocales/php53 tenemos un fichero llamado php.ini-development. Lo abriremos con un editor de textos por ejemplo el Notepad ++ y haremos estas modificaciones:
Fichero inicial Guardar como Lnea

php.ini-development php.ini
Cambios Donde dice:

El fichero php.ini no viene incluido en las distribuciones de PHP. Por esa razn debemos crearlo partiendo, en este caso, de su versin de desarrollo

Modificaciones en el fichero inicial Justificacin Asignaremos como valor de doc_root una ruta que, como observars, apunta el directorio htdocs. En otras palabras, le estamos diciendo a PHP en qu sitio del ordenador fjate que incluimos una ruta absoluta se ubicarn los ficheros cuyos scripts debe interpretar. Con esta modificacin le sealamos al intrprete de PHP en qu sitio debe buscar las extensiones que pueda necesitar para la ejecucin de sus scripts. Estas extensiones, que vienen con la instalacin de PHP, se descomprimen por defecto en un subdirectorio llamado ext y esa es la razn por la que la ruta incluida en esta modificacin apunta a un directorio con ese nombre. Descomentaremos (quitamos el punto y coma que lleva delante) la lnea alusiva a la librera php_gd2 con lo cual estamos activando la opcin de que PHP pueda ejecutar instrucciones relativas a imgenes dinmicas.

798

doc_root =
cambiar por:

doc_root=C:/ServidoresLocales/Apache/htdocs
Donde dice:

; extension_dir = "ext" 809


cambiar por:

extension_dir ="C:/ServidoresLocales/php53\ext\"
Donde dice:

950

;extension=php_gd2.dll
cambiar por:

extension=php_gd2.dll
Donde dice:

951

;extension=php_gettext.dll
cambiar por:

extension=php_gettext.dll
Donde dice:

Descomentaremos la lnea alusiva a la librera php_gettext.dll con lo cual estamos activando la opcin de incluir soporte para GNU gettext la API del NLS (Native Language Support) que permite internacionalizar las aplicaciones PHP Descomentaremos la lnea alusiva a la librera php_mbstring.dll con lo cual estamos activando la opcin que permite utilizar caracteres multibyte lo cual evita la restriccin de uso exclusivo de idiomas con un mximo de 256 carcteres

957

;extension=php_mbstring.dll
cambiar por:

extension=php_mbstring.dll
Donde dice:

959

;extension=php_mysql.dll
cambiar por:

Descomentaremos la lnea alusiva a la librera php_mysql.dll con lo cual estaremos habilitando la posibilidad de usar las funciones MySQL

extension=php_mysql.dll
Donde dice:

1085

SMTP= localhost
cambiar por:

Asignamos la direccin IP que utilizaremos para el proceso Simple Mail Transfer Protocol cuando PHP se utilizado conjuntamente con un servidor de correo para el envo de emails

SMTP = 127.0.0.1
Donde dice:

1091

;sendmail_from= me@example.com
cambiar por:

Es la direccin del remitente que utilizaremos para el envo de mensajes de correo electrnico

sendmail_from= admin@mispruebas.as
Donde dice:

1471

;session.save_path = "/tmp"
cambiar por:

session.save_path = C:/ServidoresLocales/tmp
Donde dice:

Cuando PHP utiliza sesiones es necesario establecer un lugar del servidor en que almacenar informaciones temporales relativas a ellas. Para esa finalidad hemos creado el directorio tmp e incluimos aqu la ruta absoluta hacia ese directorio

997

;date.timezone =
cambiar por:

Las ltimas versiones de PHP requieren que especifiquemos la zona horaria correspondiente al lugar donde est ubicado nuestro servidor

date.timezone ='Europe/Madrid'

Donde dice:

short_open_tag = Off 226


cambiar por:

short_open_tag = On

El caso de short_open_tag resulta particularmente interesante. En versiones anteriores se inclua la opcin ON por defecto. A partir de esta versin parece que aparecer como OFF y ser preciso cambiar su configuracin (tal como hacemos en nuestro caso) o tener en cuenta las restricciones que impone su modo OFF. Si est en modo OFF NO PERMITE la sintaxis <? ?> para incluir el cdigo PHP siendo obligatorio hacerlo mediante <?php ?> Cuando su estado es ON interpreta ambas formas de sintaxis.

Cuidado!
Es posible que no residas en Espaa. S fuera as no hay ninguna razn para que configures la zona horaria espaola en tu servidor. Qu como configuras la de tu pais? Mira aqu seguro que encuentras el valor que necesitas para tu configuracin personalizada.

Comprobacin de PHP
Una vez que hayamos modificado los apartados anteriores y guardado el fichero con el nombre php.ini en el directorio C:/ServidoresLocales/php53 llega el momento de comprobar si PHP funciona correctamente.

Un script de prueba
Para hacer esta comprobacin deberemos escribir nuestro primer script PHP. Abriremos nuestro editor Notepad++ y escribiremosexactamente esto:

<?php phpinfo(); ?>


Ahora lo guardaremos en C:/ServidoresLocales/Apache/htdocs recuerda que este es el que hemos configurado como directorio raz de servidor con el nombre info.php Recuerda tambin que es probable que el bloc de notas haya aadido la extensin .txt y que el fichero puede haber sido guardado como info.php.txt. Lo comprobaremos mirando el directorio htdocs y cambiando el nombre si fuera necesario.

Probando el primer script


Una vez instalados y configurados Apache y PHP y creado el fichero info.php, ha llegado el momento de comprobar si hemos hecho correctamente las configuraciones y si todo funciona bien. Arrancaremos el servidor Apache y una vez que tengamos la ventana de MS-DOS abierta, deberemos visualizarla sin ningn mensaje (completamente en negro). Eso significara que Apache est funcionando correctamente con el mdulo PHP. Si apareciera algn mensaje de error sera necesario corregir la lnea del fichero de configuracin a la que se aluda en el propio mensaje. Solo faltara abrir el navegador y escribir una de estas dos direcciones: http://localhost/info.php o http://127.0.0.1/info.php y aparecera en pantalla una pgina como esta:

De ser as, el proceso de instalacin y configuracin habra terminado y esa pgina nos estara facilitando toda la informacin relativa a la configuracin actual de nuestro PHP.

Cuidado!
En la configuracin de PHP (php.ini) bajo Windows debemos usar siempre la barra invertida ( \ ) a la hora de escribir los paths. Cuando tratamos la configuracin de Apache (httpd.conf) tambin bajo Windows lo hemos hecho al revs, hemos escrito todos los paths utilizando la barra normal ( / ). Ten muy presente que estas sintaxis son distintas y cuando efectes modificaciones de configuracin utiliza la adecuada a cada uno de los ficheros.

Cuidado!
Aunque nuestra configuracin de short_open_tag = On nos permite utilizar como delimitadores del cdigo PHP tanto<?php ?> como <? ?> resulta ms aconsejable inclinarse por la primera opcin ya que nos garantizara que nuestros scripts podrn ejecutarse sea cual fuere la configuracin de esta directiva. Hemos de tener en cuenta que en nuestro servidor de pruebas tenemos posibilidades de modificar la configuracin pero puede haber casos en los que no tengamos acceso a esas opciones (servicios de hosting ajenos, por citar un ejemplo) y nos surjan dificultades que nos obliguen a modificar todo nuestro cdigo. Puede resultar un poco ms incmodo agregar la coletilla php pero seguramente es lo ms aconsejable.

Instalar MySQL 5.1.56 y/o MariaDB Proceso de instalacin ySQL


En esta pgina podrs encontrar el enlace de descarga del fichero mysql-essential-5.1.56-win32.msi que contiene el fichero de instalacin de MySQL. Para descargarlo va a ser necesario que te registres como usuario. Al hacerlo te enviarn a la direccin de correo que facilites una contrasea que te permitir acceder a la descarga. Tal como hemos comentado en el caso de programas anteriores es posible que la versin que encuentres all sea ms reciente que la que he incluido en el autoinstalador. Las versiones ms antiguas de MySQL puedes encontrarlas en este enlace. Al hacer doble clic sobre su icono comienza el proceso de instalacin cuya secuencia de pantallas sucesivas puedes ir viendo en la imagen que tienes aqu debajo.

Usaremos el directorio C:/ServidoresLocales/mysql para hacer la instalacin del servidor. Configuraremos el directorio que ha de contener las bases de datos como un subdirectorio (con nombre data) del anterior.

Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Arrancar MySQL
Puesta en servicio desde la consola de MS-DOS
Una vez finalizado el proceso de instalacin ya podremos poner en marcha el servidor. Lo haremos desde el smbolo del sistema usando los comandos de MS-DOS. Para poner en marcha MySQL basta con situarnos en C:/ServidoresLocales/mysql/bin (subdirectorio bindel directorio en el que se efectu la instalacin de MySQL) mediante el comando: CD C:/ServidoresLocales/mysql/bin (subdirectorio bin y una vez all ejecutar:

A partir de ese momento el servidor MySQL ya estar activo y ya podramos gestionarlo tanto desde PHP como desde la propia consola MS-DOS.

Cuidado! En algunas versiones de Windows es posible que, al arrancar el servidor, se quede el cursor intermitente en la ventana de MS-DOS sin que regrese al prompt. Basta con cerrar la ventana Smbolo del Sistema y reabrirla. El servidor seguir activo y ya ser posible la ejecucin de comandos desde esta consola.

Apagar el servidor MySQL


Para poder apagar el servidor es necesario utilizar un nombre de usuario. En este caso utilizaremos el nombre de usuario root (el usuario que se crea por defecto). La sintaxis sera la siguiente:

Acceso a las bases de datos

Al instalar el programa se crea dentro del directorio mysql un subdirectorio llamado bin que es el que contiene los programas que gestionan las bases de datos en MySQL. Otro subdirectorio, denominado data, es destinado a contener todas las bases de datos. Cada una de ellas estar contenida en un subdirectorio diferente que tendr el mismo nombre que de la base que contiene. El instalador de MySQL crea de forma automtica dos bases de datos con los nombres: mysql ytest. No debes borrarlas! La denominada test es una base de datos que permite chequear la instalacin y la configuracin de MySQL mientras que la denominada mysql contiene, entre otros, los datos relativos a usuarios y si no est presente MySQL no funcionar. El acceso a las bases de datos MySQL requiere que los usuarios estn identificados mediante un nombre (login) y opcionalmente una contrasea (password) de acceso. El propio instalador de MySQL incluye, por defecto, un usuario con nombre root, que utiliza como password una cadena vaca. A cada usuario se le pueden asignar privilegios de modo que, por ejemplo, solo pueda realizar consultas, o acceder a tablas concretas. El usuario root goza de todos los privilegios posibles y podra ser usado para todos los supuestos. No obstante, como en situaciones reales es un usuario desaconsejable por el riesgo que entraa utilizar usuarios por defecto, vamos a crear un nuevo usuario con contrasea y con todos los privilegios que ser el que utilizaremos en los ejemplos relativos a MySQL.

Creacin de un nuevo usuario


Al nuevo usuario al que aludimos en el prrafo anterior vamos a darle los mximos privilegios (ALL PRIVILEGES) de modo que pueda gestionar cualquier base de datos, tabla y que adems pueda crearlas, borrarlas o modificarlas sin restriccin alguna. Es importante que lo creemos con la sintaxis exacta, ya que los ejemplos de los temas relacionados con MySQL estn desarrollados considerando el usuario pepe con contrasea pepa (ambas en minsculas).

Ejecutar instrucciones MySQL


El primer paso para poder ejecutar sentencias MySQL ser tener el servidor activo. Para ello habr que seguir el proceso descrito anteriormente. El paso siguiente sera especificar qu usuario va a manejar MySQL. Dependiendo de sus privilegios tendr accesos a parte o a todas las funciones. Para especificar el usuario root debemos escribir lo siguiente:

Si se tratara de un usuario con una contrasea distinta de la cadena vaca habra que aadir p detrs del nombre de usuario tal como puedes ver en esta imagen. En este caso el sistema nos pedir que escribamos la contrasea del usuario en cuestin.

Este mensaje de bienvenida y el cambio de directorio (observa que ahora el prompt ha cambiado y apunta hacia mysql) nos indican que MySQL est listo para recibir instrucciones.

Lo nico que haremos desde aqu ser crear un usuario. En adelante nos comunicaremos con MySQL a travs de la web y usando como herramienta de comunicacin el PHP.

Creacin del usuario pepe


Para crear el nuevo usuario utiliza exactamente la sintaxis que ves en la imagen.

Cuidado! El pulsar Enter en MySQL no significa como ocurre en DOS que se vaya ejecutar el comando. Si observas la imagen, hemos pulsado Enter detrs de la palabra localhost de la primera lnea y lo que ha ocurrido es que el cursor ha saltado hasta la segunda incluyendo automticamente > que significa que contina la instruccin anterior. En MySQL la ejecucin de una instruccin requiere que se haya tecleado ; inmediatamente antes del pulsar Enter.

Salir del interface de usuario


Para abandonar la interface de usuario basta con escribir exit tal como ves en la imagen. El sistema escribir su mensaje de despedida de forma automtica y el prompt regresar a C:/ServidoresLocales/mysql/bin.

Cuidado! Independientemente de que puedas crear otros usuarios con otras contraseas es imprescindible crear el usuariopepe con contrasea pepa. Todos los ejemplos que incluimos requieren este usuario.

Desinstalacin de MySQL
MySQL se desinstala desde la opcin Agregar o quitar programas como cualquier otro programa de Windows. El proceso de desinstalacin no elimina ni los ficheros ini ni tampoco el subdirectorio data. Este ltimo se conserva como medida de seguridad ya que contiene todas las bases de datos y de eliminarlo se perdera la informacin. Si en algn momento tratas de desinstalar para hacer una nueva instalacin, lo aconsejable sera mantener el directorio data y buscar y eliminar todos ficheros my.* (los ini de la instalacin anterior) antes de realizar la nueva instalacin.

Instalacin de MariaDB
Segn su pgina web oficial MariaDB es un servidor de base de datos que ofrece una alternativa funcional de reemplazo para MySQL. MariaDB est construido por algunos de los autores originales de MySQL, con la ayuda de la comunidad ms amplia de desarrolladores de software libre y de cdigo abierto. Adems de la funcionalidad principal de MySQL, MariaDB ofrece un rico conjunto de funciones mejoradas, incluyendo motores de almacenamiento alternativo, optimizacin del servidor, y los parches. Desde el punto de vista operativo podramos decir que MariaDB es a MySQL lo que LibreOffice es a OpenOffice. Es decir, son forks o derivaciones de aquellas, bajo licencia GPL (General Public License), cuyo nacimiento se justifica en los temores de lo que en un futuro pueda derivarse de las adquisin por parte de Oracle de Sun Microsystems que a su vez en propietaria de MySQL. Aunque se ofrece actualmente bajo la GNU GPL para cualquier uso compatible con esta licencia, MySQL es patrocinado por una empresa privada, que posee el copyright de la mayor parte del cdigo. Esa circunstancia es radicalmente distinta a lo que ocurre con otros proyectos como Apache, donde el software es desarrollado por una comunidad pblica y los derechos de autor estn fragmentados ya que cada porcin del cdigo es propiedad de su autor individual.

Especulaciones futuristas aparte, MariaDB est disponible en este enlace en su versin 5.3. Entre las mltiples opciones de descarga disponibles sugerimos marcar las casillas de verificacin correspondientes a Windows y a zip-file ya que no van a requerir ningn proceso de instalacin y, adems, van a permitirnos mantener en un mismo equipo una versin de MariaDB junto con otra de MySQL. Una vez hayamos descargado el fichero .zip bastara con descomprimirlo en cualquier lugar del equipo y ya estara disponible para su uso. Bastara con arrancarlo y pararlo utilizando exactamente los mismos comandos ya descritos para MySQL. La nica diferencia estara en que antes de ejecutar el comando MS-DOS mysqld de puesta en marcha de servidor habra que situar el prompt apuntando a subdirectorio bin del directorio en el que hayamos descomprimido MariaDB. El uso de una u otra base de datos slo requerira elegir el directorio bin de una u otra para ejecutar desde l los comando de puesta en marcha y parada. Respecto a la utilizacin desde PHP no hemos podido constatar diferencia funcional alguna. Es decir, todo lo descrito en estas Memorias para MySQL es absolutamente vlido, sin modificacin alguna, para el caso de que optes por usar la base de datos MariaDB.

Cuidado! Puede ocurrir que en un momento determinado no funcione correctamente MySQL (o MariaDB) y que al intentar acceder a la direccin http://localhost/phpMyAdmin/ lees un mensaje de error similar a este: #2002 - El servidor no est respondiendo (o el socket del servidor MySQL local no est configurado correctamente). Algunas veces el problema puede producirlo un exceso de limpieza. Algunas aplicaciones del tipo Ccleaner o similares pueden estar configuradas para que al ejecutarlas se borren los ficheros cuyo tamao sea cero bits. Esa accin podra eliminar algunos ficheros de ese tamao contenidos el subdirectorio /data/mysql y su inexistencia puede ser la causa del problema. Para comprobarlo podemos editar un fichero con extensin .err que suele tener el mismo nombre que el equipo y que est en el subdirectorio /data de mysql. Se identifica facilmente porque es el nico con esa extensin. Si vemos que contiene lneas similares a estas: [ERROR] Fatal error: Can't open and lock privilege tables: File '.\mysql\host.MYD' not found (Errcode: 2)n> File '.\mysql\plugin.MYD' not found (Errcode: 2 File '.\mysql\time_zone_leap_second.MYD not found (Errcode: 2) File '.\mysql\servers.MYD' not found (Errcode: 2) bastara con crear ficheros nuevos (desde el mismo bloc de notas) en blanco (sin ningn contenido) y guardarlos con esos nombres en el subdirectorio /data/mysql. Reiniciaramos el servidor y MySQL (o MariaDB) volvera a funcionar correctamente.

Instalando phpMyAdmin
Qu es PHPMyAdmin?
PHPmyAdmin es simplemente un conjunto de utilidades y scripts escritos en lenguaje PHP que permiten gestionar bases de datosMySQL a travs de una pgina web. Mediante esta herramienta, sin conocer el lenguaje MySQL, podremos modificar, consultar, crear y borrar tanto bases de datos como tablas y registros contenidos en ellas incluyendo la gestin de usuarios recuerda que MySQL requiere claves y contraseas y susprivilegios de acceso. La versin de MySQL para Windows no dispone de una interface propia que permita gestionar sus bases de datos a travs de Windows. La nica posibilidad de gestin es a travs de MS-DOS y eso requiere que el usuario sepa utilizar los comandos propios de las funciones MySQL. Sin esos conocimientos de SQL, tendramos como recurso la posibilidad de gestionar las bases de datos a travs de nuestros propios scripts PHP, pero eso nos exigira conocer con una cierta profundidad a medida que avancemos lo iremos logrando las funciones que PHP posee para este tipo de labores. Es por eso que este conjunto de herramientas resulta muy cmodo y fcil de utilizar y est convirtindose de hecho ya lo es en el soporte estndar que la mayora de los hosting facilitan a sus usuarios para gestionar las bases de datos alojadas en sus servidores.

Instalacin de PhpMyAdmin

En el sitio http://www.phpmyadmin.net/ hay un enlace para la descarga del fichero phpMyAdmin-3.3.10-all-languages.zip. Tal como venimos comentando en pginas anteriores es posible que ya se hayan producido actualizaciones y la versiones que veas no coincidan exactamente con la que aqu te referimos. No suele tener mayor transcendencia. Las versiones histricas de phpMyAdmin puedes encontrarlas en este sitio. El fichero zip obtenido en la descarga tenemos que descomprimir obligatoriamente (contiene scripts de PHP) en el directorioC:/ServidoresLocales/Apache/htdocs. Al hacerlo se crear un directorio llamado phpMyAdmin-3.3.10-all-languages al que vamos a cambiar el nombre por otro ms cmodo y fcil, dado que al utilizar phpMyAdmin tendremos que escribir el nombre de ese directorio con bastante frecuencia. Vamos a renombrarlo como phpMyAdmin. Ser necesario editar el fichero Config.class.php (contenido en el subdirectorio libraries de phpMyAdmin) y modificar la lnea n 25. Dnde dice: var $default_source = './libraries/config.default.php''; deberemos poner: var $default_source = './libraries/config.inc.php'; En el mismo subdirectorio libraries hay un fichero llamado config.default.php. Abrmoslo con nuestro editor Notepad ++, guardmoslo (sin hacer ninguna modificacin) con el nombre config.inc.php y, ya en este ltimo fichero, hagamos los cambios que se detallan en la tabla siguiente.

Fichero inicial Guardar como Lnea

config.default.php config.inc.php
Cambios Donde dice:

Modificaciones en el fichero config.inc.php

40

$cfg['PmaAbsoluteUri'] = '':
cambiar por:

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpmyadmin/';
Donde dice:

177

$cfg['Servers'][$i]['auth_type'] = 'cookie';
cambiar por:

$cfg['Servers'][$i]['auth_type'] = 'config';
Donde dice:

227

$cfg['Servers'][$i]['nopassword'] = false;
cambiar por:

$cfg['Servers'][$i]['nopassword'] = true;
Donde dice:

363

$cfg['Servers'][$i]['AllowNoPasswordRoot'] = false;
cambiar por:

$cfg['Servers'][$i]['AllowNoPasswordRoot'] = true;

Hechas las modificaciones en ambos ficheros ya estaremos en condiciones de probar su funcionamiento.

Prueba de funcionamiento de phpMyAdmin


Arranquemos Apache dejando minimizada su ventana MS-DOS y arranquemos tambin MySQL. Con ambos servidores activos escribamos en el navegador la direccin: http://localhost/phpmyadmin/. Deber abrirse una pgina como esta:

Explorando los enlaces de la parte izquierda de la pantalla -mysql(23)- podremos visualizar los contenidos de la tabla user que nos dar una imagen como esta:

dnde podemos ver la lista de usuarios actuales y sus privilegios. Vemos el archi mencionado usuario root y tambin al nuevo usuariopepe con su contrasea encriptada. Las columnas marcadas con Y/N contienen las tablas de privilegios de cada usuario. Observa que tantoroot como pepe tienen todos los privilegios, mientras que, el tercer usuario (con nombre en blanco y creado durante la instalacin de MySQL) no tiene ninguno.

Instalacin del servidor FileZilla FTP Qu es un servidor FTP?


Conceptualmente un servidor FTP no difiere en nada de un servidor HTTP. Las diferencias entre los diversos tipos de servidores estriban en los programas que usan software de servidor en el tipo de peticin que aceptan y en el protocolo que requieren las peticiones que atiende.

En el caso de Apache se trata de un servidor HTTP porque slo acepta peticiones a travs de ese protocolo. Al hablar de servidores FTP nos referimos a aquellos que nicamente aceptan peticiones realizadas por medio del protocolo conocido como FTP (File TransferProtocol). Como en todos los dems casos, la comunicacin cliente-servidor requiere el uso por parte de ambos del software adecuado a su protocolo concreto.

Clientes FTP
Para hacer una peticin FTP, igual que en cualquier otro caso de peticin, necesitamos disponer del software adecuado para realizarla. Recuerda que, en realidad, un cliente no es otra cosa que el programa que se utiliza para realizar un determinado tipo peticin a unservidor. Existen varios clientes FTP en el mercado. Si no dispones de ninguno descargar FileZilla Client desde el sitio de FileZilla. Las versiones ms modernas de algunos navegadores tambin permiten realizar peticiones mediante este protocolo. Si escribimos en la barra de direcciones del navegador se requiere la versin 5 superior de Internet Explorer :ftp://super:superi@localhost y un servidor FTP con nombre localhost est activo, veremos que aparecen en la ventana del navegador los iconos de los ficheros contenidos en el directorio root del servidor y que, a la vez, se nos ofrece la posibilidad de: borrar archivos; crear subdirectorios; copiar ficheros (desde el servidor a cualquier otro directorio de nuestro ordenador o viceversa) sin ms que seguir mtodos idnticos a los que se utilizan habitualmente en Windows. El acceso a un servidor FTP salvo que permita el acceso de forma annima requiere del cliente tres datos: nombre del servidor,nombre de usuario y contrasea, que son los que aparecen en azul un poco ms arriba. En esa direccin aparecen marcados en rojo:(ftp://) que indica el tipo de protocolo que se utiliza en la peticin; (:) cuya finalidad es la de actuar como separador entre el nombre de usuario y la contrasea; y, (@), que hace tambin funcin de separador, en este caso entre la contrasea y el nombre del servidor. An a riesgo de parecer reiterativos, queremos insistir en que para que una peticin, como la que comentamos, pueda ser atendida se requiere, de forma imprescindible, que exista un servidor FTP activo. Hay una posibilidad aadida. Mediante funciones de PHP tambin es posible gestionar servidores FTP sin necesidad de recurrir a ningn cliente especfico. Lo trataremos en los contenidos de programacin relativos a las funciones FTP.

Instalacin de un servidor FTP


Se trata del instalador de un servidor FTP, que puedes descargar desde FileZilla_Server-0_9_37.exe y que tambin puedes encontrar en esta pgina. Igual que en pginas anteriores las versiones ms antiguas podemos encontrarlas aqu. Una vez descargado el instalador ya podemos seguir la secuencia de instalacin que puedes ir viendo en esta imagen.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Arrancar y apagar el servidor

Despus de instalar el servidor aparecern en Programas un grupo con unos iconos como estos. Como resulta obvio, el sealado con Start permite la puesta en marcha del servidor y el sealado con Stopsirve para detener su funcionamiento. La opcin Server Interface para usarla es necesario que previamente hayamos puesto en marcha el servidor permite configurar del servidor y controlar su funcionamiento. Nos valdremos de l para llevar a cabo la configuracin de nuestro servidor FTP y nos permitir visualizar el estado del servidor y el registro todas las acciones que se realicen en l. Si has optado por la instalacin automtica de todos los programas bastar con que pulses sobre el icono correspondiente al servidor FTP desde la ventana de Gestin de Servidores.

Cuidado! Sobre Windows Vista y/o Windows 7 es necesario ejecutar este programa con privilegios de administrador. En vez de doble clic tpico pulsa con el botn derecho del ratn y elige la opcin de ejecutar como Administrador.

Definicin de los servicios

La imagen que tienes a la izquierda representa la forma ms compleja de la configuracin que pretendemos desarrollar en esta instalacin. Empezaremos por su forma ms sencilla. Para ello crearemos el directorio C:\servidorFTP que ser el directorio raz (o root) de nuestro servidor FTP. Igual que ocurra en el caso de Apache podra ser un directorio cualquiera de los existentes en el ordenador en el que tengamos instalado el software de servidor. Supongamos que nuestra intencin ofrecer tres servicios que requieren crear los subdirectorios:C:\servidorFTP\Alumnos, C:\servidorFTP\Documentacion y C:\servidorFTP\Gestion. Por el momento nos resultar suficiente con estos tres directorios. Ms adelante, para una configuracin ms avanzada, deberamos crear toda la estructura que puedes ver en la imagen con la excepcin de juan (sombreado en rojo) que se generara de forma automtica. Crearemos tres usuarios bsicos. A uno de ellos le llamaremos super (usuario que administra el sistema) y permitiremos que pueda acceder sin restriccin alguna a todo el contenido del directorioC:\ServidorFTP y de todos sus subdirectorios. Un segundo usuario llamado webmaster habr de tener iguales privilegios en el Document Root del servidor Apache (C:/ServidoresLocales/Apache/htdocs). El tercer usuario, secre, podr acceder tambin sin restricciones a los directoriosC:\ServidorFTP\Documentacin y C:\ServidorFTP\Gestion.

Cada usuario ha de disponer de un directorio raz (su root) que ha de contener todos los directorios a los que va a tener acceso aunque el hecho de que un directorio sea el root de un usuario no implica que pueda acceder a todos sus contenidos ya que para hacerlo es necesario que tenga -adems- permisos de acceso. Tal es el caso del usuario secre cuyo root ha de ser C:\ServidorFTP\ pese a que no va a tener privilegios de acceso al directorio Alumnos.

Privilegios de los usuarios


Esta ser la manera en la que asignaremos contraseas y privilegios a cada uno de los usuarios. Usuario super con contrasea superi. Sus privilegios en los diferentes directorios sern: Todos los privilegios en C:\servidorFTP. Al ser el usuario super parece razonable concederte el mayor grado de libertad. Usuario webmaster con contrasea superi. Tendr los privilegios siguientes: Todos los privilegios en C:/ServidoresLocales/Apache/htdocs. Las razones son idnticas al caso anterior. Usuario secre con contrasea superi. Va a tener los siguientes privilegios: List en c:\ServidorFTP. Al concederle este privilegio podra visualizar (al acceder a su root mediante un cliente FTP) la lista de directorios y documentos que contiene. Si no incluyramos esta opcin el cliente FTP nos dara un mensaje de error al acceder al root (no tendra permiso alguno) y obligara al usuario secre a establecer como root alguno de los directorios para los que tiene permiso de acceso. Todos los privilegios en Documentacin. Se entiende que este usuario es quien realiza la gestin completa de este directorio. Todos los privilegios en Gestin. Las razones son idnticas a las del caso anterior. En este enlace tienes el detalle y la justificacin de los diferentes privilegios que hemos establecido para cada uno de los restantes usuarios y grupos de usuarios que conforman la opcin ms compleja de nuestra propuesta.

Configuracin de FileZilla Server


Server Interface
Al activar el Server Interface por primera vez aparece una ventana como la que tienes aqu debajo. Si marcas la casilla de verificacin y pulsas OK ya no aparecer en posteriores arranques.

Aparecer una nueva ventana como la que puedes ver en esta otra imagen.

El primero de los iconos permite arrancar y detener el servidor desde esta consola. El segundo (en forma de candado) permite bloquear y desbloquear el servidor sin necesidad de detenerlo. Desde el tercero podremos hacer modificaciones generales en la configuracin. Optaremos por dejarlas con las opciones por defecto. Desde el cuarto, uno de los ms interesantes para nuestros propsitos, podremos crear cuentas de usuarios as como realizar su configuracin. El quinto de los iconos muy similar al anterior permite acceder a la configuracin de grupos de usuarios.

Creacin de cuentas de usuario


Empezaremos creando las tres cuentas de los usuarios bsicos: super, webmaster y secre utilizando las contraseas que hemos definido anteriormente. La forma de hacerlo es la que ves en la imagen inferior. Se pulsa en el icono user de la ventana Server interface (el cuarto de los iconos de la imagen que tienes aqu arriba) y aparece la ventana que ves en la parte inferior. La secuencia de creacin de un usuario es la siguiente: Selecciona general (1). Pulsa en el botn Add de la ventana de usuarios (2). Se abrir una nueva ventana. Se escribe -en la nueva ventana- el nombre de usuario(3). Se deja la opcin None (por defecto) en el men de opciones User should.. (4) y se pulsa el botn OK (5).

Al pulsar ok se cierra y se la ventana Add user account. Se marca las opcin Enable account (6). Se marca la casilla de verificacin Password (7) y se escribe la contrasea de usuario (8).

Repetiremos el proceso hasta crear las cuentas de los dos usuarios indicados al comienzo de este prrafo y acabaremos pulsando el botn OK que est situado en la parte inferior izquierda de la ventana de usuarios.

Eleccin de los roots los directorios accesibles y privilegios de cada usuario


A definir los servicios hemos decidido que al usuario webmaster se le va a permitir nicamente el acceso aC:/ServidoresLocales/Apache/htdocs (para la gestin del servidor Apache) por tanto su root ha de ser el directorioC:/ServidoresLocales/Apache/htdocs. Para el caso de super (el usuario que controla en su integridad el servidorFTP) hemos optado por c:\servidorFTP como root y cuando se trata del usuario secre hemos dicho que vamos a permitrle el acceso a c:\ServidorFTP\Documentacion y a c:\ServidorFTP\Gestiony que por ello hemos de establecer como root el directorio c:\ServidorFTP (nivel superior a ellos y que, por tanto, los contiene a ambos). El caso del usuario secre no es tan particular como pueda parecer ya que es bastante frecuente el hecho de que un usuario no deba acceder a los contenidos de todos los subdirectorios de su root. Cada uno de los directorios accesibles para un usuario (Shared folders) puede gozar de privilegios distintos. Al seleccionar un directorio se activan las casillas de verificacin que ves en la imagen y desde ellas se pueden conceder privilegios a dos niveles: ficheros ydirectorios. A nivel de ficheros cuenta con las opciones Read (descargar), Write (escribir, subir), Delete (borrar) y Append (aadir a un fichero preexistente cuando la transferencia ha sido interrumpida). Cada una de ellas puede configurarse como opcin permitida no permitida. Cuando se trata de directorios las opciones (tambin puede configurarse cada una de ellas como permitida/no permitida) son: Create(Crear), Delete (borrar), List (ver una lista de los contenidos) y +SubDirs (Cuando est activado asigna automticamente a todos los subdirectorios que contenga los mismos privilegios que al directorio actual). El proceso de establecimiento de la accesibilidad de un directorio (y la concesin de privilegios) es la que se detalla en la imagen. Se accede desde el icono users de la ventana Server Interface siguiendo la siguiente secuencia: Se elige Shared Folder en la ventana de la izquierda (1). Se elige un usuario User en la ventana de la derecha (2). Se pulsa en el botn Add en la parte central de la ventana (debajo de Shared Folders) (3) con lo que se abre automticamente la ventana Buscar carpeta. Se elige un directorio (4) y se pulsa sobre el botn Aceptar (5).

Se establecen los privilegios -marcando o desmarcando las casillas de verificacin correspondientes- para el directorio elegido (6). Se pulsa OK para guardar los cambios de configuracin (7). El proceso puede repetirse cuantas veces sea necesario.

Directorios accesibles por los usuarios super y webmaster


Esta es la configuracin del usuario super.

Para el usuario webmaster procederamos de forma idntica. La nica diferencia sera el directorio (C:/ServidoresLocales/Apache/htdocs) sobre el que estableceramos los mismos privilegios que se ven en la imagen para el usuario super.

Directorios accesibles por del usuario secre

La razn de estas asignaciones es posibilitar la eleccin de uno de los dos directorios Documentacion y Gestion con todos los privilegios. Como quiera que existe otro directorio del mismo nivel (Alumnos) al permitirle nicamente listar el que los contiene este ltimo le resultara inaccesible.

Observars que el directorio raz est marcado con la letra H. Para cambiarlo bastar con seleccionar otro cualquiera y pulsar sobre el botn que ves en esta imagen.

Acceso de usuarios
La direccin localhost apunta siempre hacia el directorio root de usuario. Eso quiere decir que si utilizando el FileZilla Client escribimos esa direccin y nos identificamos como secre (indicando la contrasea de usuario) veramos algo como esto:

que como puedes observar no es otra cosa que la visualizacin de los contenidos del directorio C:\ServidorFTP (el root de este usuario. Si nuestro equipo estuviera conectado a una red de rea local podramos acceder al servidor FTP escribiendo en vez de localhost la direccin IP del equipo en el que tuviermos instalado el servidor.

Cuidado! Es posible que el firewall de Windows nos bloquee el acceso al servidor FTP sin darnos ningn mensaje de advertencia. Lo ms conveniente para evitar problemas de esta ndole sera abrir Paneles de Control -> Firewall de Windows -> Excepciones y, una vez all, pulsar el botn Agregar Programas y aadir Filezilla Server.exe

Utilizacin de alias
Este servidor tambin permite ser configurado para la utilizacin de Alias. Pulsando con el botn derecho del ratn sobre el nombre de uno de los directorios aparece un men como este:

al elegir la opcin Edit Aliases se abre una ventana como la que ves aqu debajo. Si introducimos en ella la ruta absoluta completareemplazando el nombre del ltimo directorio por una palabra distinta (en el ejemplo hemos incluido web) estaremos creando un alias. Podremos crear tanto como deseemos, es cuestin de incluirlos (completos) uno a continuacin de otro separados por el carcter |.

Una vez creados los alias podremos utilizarlos para acceder a los espacios (sustituyendo el nombre del directorio por el alias). Aqu tienes imgenes del ejemplo. Observars que localhost/ServidoresLocales/Apache, localhost/servidor y localhost/indio nos conducen al mismo sitio.

Una configuracin ms compleja


Creacin de grupos de usuarios
La configuracin de grupos de usuarios es una opcin que ofrece bastante inters. Mediante esta opcin se pueden establecer privilegios comunes a una serie de usuarios. Ello facilita la configuracin cuando se trata de grupos numerosos que van a compartir directorios y privilegios. Sigue un proceso muy similar al que hemos descrito para el caso de usuarios. Las diferencias ms sustanciales son: Se accede a travs del icono groups (el quinto de la ventana Server Interface). No requiere insertar contraseas. Estas sern privilegio exclusivo de los usuarios del grupo. Requiere activar la casilla de verificacin Enable access for users inside group. En nuestro ejemplo, crearemos cuatro grupos: ingles (grupo de los profesores de Ingls), infor (profesores de Informtica), ciclo1(alumnos de primer ciclo) y ciclo2 alumnos de segundo ciclo.

Directorios accesibles y privilegios del grupo


La configuracin de los directorios accesibles y de los privilegios en cada uno de ellos es idntica a la descrita para el caso de usuarios no pertenecientes a un grupo. Al avanzar en esta configuracin ya sera necesario tener disponible la estructura de directorios y subdirectorios que se refleja en la imagen que tienes un poco ms arriba. La nica diferencia estriba en que aade una nueva e interesante posibilidad a travs de la opcin Autocreate. Supongamos que pretendemos que cada uno de los alumnos de nuestro supuesto disponga de un subdirectorio propio para podersubir y gestionar sus propios trabajos de cada materia. Aparte de la ventaja de tener separadas sus actividades con la posibilidad de borrar,aadir, modificar, etctera dentro de su propio espacio y a la vez impedir que pueda efectuar esos procesos en materiales ajenos. Eso requerira ir creando esos directorios para cada uno de los usuarios y esa podra ser una tarea lenta y pesada. Mediante la opcinAutocreate se puede configurar un directorio de forma que durante el primer acceso del usuario se cree de forma automtica un subdirectorio con el mismo nombre que el del usuario. El uso de esta opcin requiere: Incluir en Shared folders la ruta del directorio base (en el que pretenden crearse los subdirectorios de cada uno de los usuarios pertenecientes al grupo) acabada con /:u

Asignacin de usuarios a un grupo


Una vez creado un grupo (o grupos) es necesario asignar los usuarios a ese grupo. El proceso es muy similar al de creacin de usuarios no adscritos a ningn grupo. La nica diferencia est en el punto (4) del proceso, ya que ahora hemos de elegir el grupo al que va a pertenecer el usuario (antes elegamos none). En el ejemplo hemos incluido dos usuarios por cada uno de los grupos: profe_ingles1 y profe_ingles2 en el grupo ingles. profe_infor1 y profe_infor2 en el grupo infor. ciclo1_alumno1 y ciclo1_alumno2 en el grupo ciclo1. ciclo2_alumno1 y ciclo2_alumno2 en el grupo ciclo2. En todos los casos hemos incluido una contrasea idntica al nombre de usuario.

Los miembros de un grupo recogen automticamente todos los privilegios del Shared Folder del grupo al que pertenecen. No obstante, es posible aadir nuevos directorios y privilegios (aadidos a los especficos del grupo al que pertenecen) incluyndolos en elShared Folder del usuario. En este enlace tienes el detalle y la justificacin de los diferentes privilegios que hemos establecido para cada uno de los grupos de usuarios.

Cuidado! En este fichero, servidorftp.rar, tienes la estructura de directorios aqu descrita. Bastar con que la descomprimas en el directorio raz de tu equipo para que puedas utilizarla con los ejemplos aqu descritos.

Fichero de configuracin de Filezilla Server


Dado que, por el nmero de usuarios y por la complejidad de la estructura, la labor de configuracin y creacin de los diferentes usuarios aqu propuestos puede resultarte lenta y tediosa hemos incluido un fichero que puedes obtener http://www.rinconastur.com/php/filezilla.zip Si descomprimes su contenido -FileZilla Server.xml- en el directorio de instalacin de Filezilla Server (por defecto sera un directorio con ese mismo nombre dentro de Archivos de programa) sobrescribiendo el existente ya dispondrs de todos los usuarios y grupos aqu descritos junto con sus configuraciones respectivas.

Cuidado! En el enlace que figura en el prrafo anterior y aqu tienes la configuracin de los diferentes usuarios tal como se describen en esta pgina y en sus anexos.

Instalacin de un servidor de correo


Instalacin de Mercury Mail
El software de servidor de correo Mercury Mail est disponible en http://www.pmail.com donde puedes elegir la descarga de Mercury mail transport system for win32 and NetWare systems v.4.73 o bien directamente desde aqu. El proceso de instalacin es el que describen las imgenes siguientes:
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Los aspectos ms significativos de este proceso son los siguientes: Elegiremos como direccin local la IP 127.0.0.1 pensando exclusivamente en servidor para pruebas. Si quieras utilizarlo como servidor de correo en una red local habrs de sustituir la IP 127.0.0.1 por la correspondiente al ordenador en el que est instalado el servidor Para poder trabajar con cuentas externas a nuestra instalacin local hemos de tener en cuenta que en la ventana dnde dice:Address of host via which to send mail tenemos que incluir la direccin del servidor SMTP a travs del que se enviaran los mensajes a direcciones de correo externas. En las pruebas hemos utilizado varias (los SMTP de nuestras cuentas de correo) aunque, como ves en la imagen, la prueba definitiva la hemos hecho utilizando la direccin del servidor de usuarios de Educastur (smtp.educastur.princast.es), ya que su proceso de configuracin tiene la forma ms compleja dado que ese servidor requiere autentificacin del usuario.

Configuracin de PHP
Para que nuestro servidor de correo pueda ser utilizado mediante funciones de PHP es necesario que el fichero de configuracin de PHP, (php.ini) contenga los cambios ya propuestos al hablar de la configuracin de PHP. All habamos modificado concretamente las dos directivas: SMTP = 127.0.0.1 y sendmail_from=admin@mispruebas.as . Como es lgico, en el caso de optar por la instalacin de una red de rea local la IP asignada a SMTP habra ser la del equipo en el que estuviera instalado el servidor.

Arrancar y parar el servidor


Para arrancar el servidor hay que ejecutar el programa Mercury Loader. Lo encontrars en el directorio en que hayas instalado el servidor de correo (C:/ServidoresLocales/Mercury). Sabremos que est en marcha porque aparecer una ventana nueva. Si la minimizamos aparecer en la barra de tareas un icono como este.

Este icono solo aparece al minimizar la ventana. Si la cerramos se parar el servidor y desaparecer el icono. Aparte de la opcin anterior, desde el men del servidor tienes acceso a esta opcin que ve en la imagen.

Cuando est funcionando el servidor para pararlo aparece un texto como este. Si estuviera parado, se podra activar desde la misma opcin. Ahora aparecera con el texto: Leave offline mode

Configuracin del servidor de correo


Aadir usuarios y crear un dominio local
Esta imagen describe paso a paso el proceso de creacin de usuarios y configuracin de un dominio local. Crearemos dos dominios locales llamados localhost y mispruebas.as y aadiremos los usuarios juan, perico y andres a quienes pondremos contraseas idnticas a los nombres respectivos.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Un script de prueba
Este es el cdigo fuente de un script que nos permitir comprobar si hemos configurado correctamente el servidor de correo. El contenido que aparezca en la pgina nos dir lo que ha ocurrido. No te preocupes si an no entiendes el cdigo! Ya hablaremos de l ms adelante.

<?php if( mail("juan@mispruebas.as", "Una prueba definitiva","Bienvenid@ a PHP", "From: Administrador de mispruebas.as <admin@mispruebas.as> Reply-To: juan@mispruebas.as Cc: perico@mispruebas.as Bcc: andres@mispruebas.as X-Mailer:PHP/" . phpversion())){ print "Mensajes enviados con exito"; }else{ print "Se ha producido un error"; } ?>

Configuracin del cliente de correo


La configuracin del cliente de correo Outlook Express o similar no plantea problemas. El proceso es muy similar a la configuracin de cualquier otra cuenta de correo. Los nicos detalles a tener en cuenta son los relativos a la configuracin de los servidores SMTP y POP3. En ambos casos se escribe la IP con la que hemos configurado el servidor, es decir: 127.0.0.1 o la del equipo que soporte el servidor en el caso de una red local. Como nombre de cuenta pondremos el mismo con el que las hemos creado (juan, perico, andres) sin aadir la @ ni el nombre del dominio.

Pruebas del servidor


Una vez configuradas las cuentas en el cliente de correo bastar con enviar mensajes a las direcciones de usuarios locales (con el servidor Mercury activo) y comprobar que son recibidos en las cuentas destinatarias.

La segunda de las pruebas el funcionamiento a travs de PHP podremos hacerla arrancando ambos servidores (Apache y Mercury) pulsando en el enlace que tienes un poco ms arriba y comprobando despus, a travs del cliente de correo, que se ha recibido el mensaje en las cuentas de los tres usuarios de pruebas.

Leer mensajes de cuentas externas


Puede resultarte interesante configurar el servidor de correo de forma que puedan recibirse en una cuenta local los mensajes enviados a una -o varias- cuenta externas. Se trata de el servidor local compruebe y descargue los eventuales mensajes que pudieran haberse recibido en una cuenta externa. En esta imagen tienes, a modo de ejemplo, la descripcin de la configuracin de este servidor para que el usuario juan pueda leer desde su cuenta local los mensajes recibidos en la de educastur.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Enviar mensajes a cuentas externas


Mercury permite enviar mensajes (a travs del servidor configurado como Address of host via which to send mail ) a direcciones de correos correspondientes a dominios externos. La configuracin de esa opcin requiere el proceso que puedes ver aqu debajo. All tiene la forma de configurar el servidor para que permita el envo de mensajes a direcciones no locales a travs del servidor smtp externo que hemos configurado al efectuar la instalacin. Al enviar mensajes desde una cuenta local hacia una cuenta externa la direccin de respuesta por defecto sera la local. Eso, obviamente, planteara problemas al destinatario ya que sus respuestas no encontraran ese dominio en la red. Bastara con modificar la configuracin del cliente de correo incluyendo como direccin de respuesta la de una cuenta externa.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Cuidado! La gestin de mensajes externos puede plantear problemas derivados de los filtros antispam de los servidores de correo de la red que pueden bloquear el envio o recepcin de los mensajes enviados utilizando este servidor.

Desinstalacin del servidor de correo


Durante la instalacin de Mercury no se escribe nada en el registro de Windows. Por ello, el proceso de desinstalacin no existe. Basta con borrar del directorio de instalacin y habremos desinstalado el servidor.

Cifrado con clave simtrica


Comunicacin segura
El objetivo de la comunicacin segura es que la confidencialidad de informacin transmitida evitando tambin el riesgo de que pueda ser modificada o manipulada durante el proceso de intercambio. Por medio del protocolo SSL Secure Socket Layer (una de las opciones ms populares) se puede ocultar a ojos de teceros la informacin que fluye, de forma bidireccional, entre el servidor y el cliente. Para lograr tales propsitos es necesario recurrir a alguno de procedimientos criptogrficos que describiremos a continuacin.

Cifrado simtrico
Supongamos que A y B convienen enviarse mensajes cifrados y acuerdan reemplazar las vocales por los nmeros 1 al 5. De esa forma cuando uno de ellos pretenda escribir la palabra poetisa utilizar la grafa: p42t3s1. El receptor del mensaje podr reemplazar los nmeros por su vocal equivalente y recomponer el mensaje. Este sera un ejemplo muy simple de cifrado simtrico o con clave privada.

El grado de inseguridad de un sistema de cifrado simtrico est condicionado por dos factores. Uno de ellos, comn a todos los sistemas de cifrado, es la mayor o menor resistencia que pueda presentar a los intentos de descubrir la clave a base de ensayo y error(fuerza bruta). Normalmente, un aumento del tamao de la clave representa un incremento la seguridad. El otro problema, el ms grave, es la falta de certeza sobre la identidad de remitente. No hay nada que nos de garantas sobre quienha cifrado el documento. De todas formas veremos un poco ms adelante como subsanar estos inconvenientes ya que este es el mtodo de cifrado que se utiliza habitualmente cuando se navega por pginas seguras. Existen varios algoritmos de cifrado simtrico. Uno de los ms populares es el conocido como DES adoptado como un estndar, para comunicaciones no clasificadas, por el Gobierno de los EE.UU. en 1976. Su grado de eficiencia qued muy cuestionado cuando, en 1998,Electronic Frontier Foundation logr fabricar una mquina capaz de descifrarlo en tres das. Esta circunstancia forz la aparicin de versiones mejoradas tales como el DES mltiple y otras que han logrado paliar en gran medida sus deficiencias iniciales y hacer de DES mltiple un algoritmo de uso bastante frecuente. El algoritmo IDEA (International Data Encryption Algorithm) es otro de los que aperecen, en este caso en 1992, como opciones alternativas al uso de DES mltiple. No fu el nico. En octubre de 2000 el National Institute for Standards and Technology (NIST) adopt del algoritmo RIJNDAEL como nuevo Estndar Avanzado de Cifrado (AES) para su empleo en aplicaciones criptogrficas no militares. PHP5 dispone de funciones de cifrado para una gran variedad de algoritmos. Aqu tienes una lista de los algoritmos de cifrado que soporta actualmente.

Adems de los distintos algoritmos de cifrado hay otro elemento diferenciador. Se trata de lo conocido como modo de cifrado. Los algoritmos de cifrado suelen trabajar con bloques de longitud fija. La cadena objeto del cifrado es descompuesta en bloques de igual tamao y tratada de diferentes modos. En los llamados ECB (Electronic CodeBook) cada bloque es cifrado de forma independiente. En otros modos, por ejemplo el CBC (Cipher Block Chaining), a cada bloque de texto plano se le aplica una operacin que requiere el uso del texto de bloques anteriores. En estos casos, para hacer cada mensaje nico ha de utilizarse un vector de inicializacin. Aqu tienes la lista de los modos de cifrado soportados por tu versin de PHP.

Funciones PHP de cifrado simtrico


Configuracin de PHP
PHP dispone de funciones que permiten efectuar algunos tipos de cifrado. Antes de nada y como siempre en estos casos es conveniente comprobar en el fichero info.php si estn activadas estas opciones.

En el caso de la versin PHP 5.3.6 para Windows esta opcin viene activada por defecto. Igual ocurre en el caso de PHP 5.3 en Ubuntu 10.10. Por el contrario, en versiones anteriores de PHP es necesario, adems de seguir el proceso de configuracin que se indica en el enlace, descomentar de su fichero php.ini, quitando el punto y coma (;) que por defecto lleva delante la extension=php_mcrypt.dll. Si en alguna versin de Ubuntu no viniera configurado por defecto podra instalarse ejecutando desde la consola el siguiente comando:

sudo apt-get install php5-mcrypt

Proceso de cifrado y descifrado


Los procesos de cifrado y descifrado mediante PHP son muy similares y requieren, en ambos casos, la siguiente secuencia de funciones: $identificador=mcrypt_module_open(algoritmo, ubicacion, modo, directorio) Abre un nuevo mdulo de cifrado identificado por el valor la variable $identificador. Requiere estos parmetros: algoritmo es una cadena que ha de contener, entre comillas, el nombre del algoritmo que pretendemos utilizar. Ser uno de los nombres de la lista antes mencionada y que puedes ver nuevamente desde este enlace. El parmetro ubicacion permite especificar el directorio con la eventual ubicacin del algoritmo de cifrado en el caso de que se usara uno distinto a los incluidos en la distribucin de PHP. Lo habitual ser que pongamos como valor una cadena vaca de la forma "". El parmetro modo ser una cadena en la que se especifique el modo de cifrado que pretendamos utilizar y habr de contener uno de los valores (escrito entre comillas) que tenemos en este enlace. Por ltimo, el parmetrodirectorio ser habitualmente una cadena vaca "" ya que est definida para establecer el modo del directorio eventualmente establecido en el parmetro ubicacion. Iniciado el mdulo de cifrado y segn el modo de cifrado establecido puede resultar necesario crear un vector de inicializacin cuya longitud se determina por medio de la funcin: $longitud=mcrypt_enc_get_iv_size($identificador)

en la que $identificador es el identificador de recurso establecido por la funcin anterior y $longitud la longitud de del mencionado vector de inicializacin. Conocida la dimensin $longitud del vector de inicializacin (puede ser cero en el caso de que no sea requerido su uso) debemos crearlo invocando la funcin: $vector=mcrypt_create_iv($longitud, constante) donde $longitud es resultado de la funcin anterior y constante es la constante MCRYPT_RAND que debemos incluir sin comillas. El resultado, $vector, ser el vector de inicializacin. El paso siguiente ser iniciar todos los buffers necesarios para el posterior proceso de cifrado o de descifrado. De esa labor se encarga la funcin: mcrypt_generic_init($identificador, clave, $vector) en la que $identificador es el identificador del recurso, clave es una cadena que se usar como CLAVE DE CIFRADO y $identificador el identificador del recurso y $vector es el vector de inicializacin. El ltimo paso ya ser el cifrado o descifrado propiamente dichos. Si se trata de cifrar utilizaremos: $cifrado=mcrypt_generic($identificador, texto) donde texto es una cadena (o variable) que contiene el texto que pretendemos cifrar y donde $identificador sigue siendo el identificador del recurso. El resultado del cifrado es recogido en la variable $cifrado Si se trata de descifrar la funcin anterior debe ser sustituida por $descifrado=mdecrypt_generic($identificador, $cifrado) siendo $cifrado la variable (ocadena) cifrada que pretendemos desencriptar y $descifrado el resultado de la desencriptacin. Llegados a este punto, solo nos restara liberar los buffer reservados para el cifrado y cerrar el recurso mediante las funciones: mcrypt_generic_deinit($identificador) y mcrypt_generic_close($identificador) De esta forma se consigue un mtodo de cifrado y descifrado aplicable con cualquiera de los algoritmos y modos de cifrado disponibles.

Ejemplos de cifrado y descifrado simtrico


Un ejemplo de como puede cifrarse con clave simtrica podra ser este:

<?php # establecemos la clave y la cadena a encriptar $clave = "clave"; $texto ="Esta es una cadena de prueba"; /*creamos un identificador de encriptado en el que indicamos el tipo de cifrador (cast-128) y el modo de cifrado (ecb) */ $ident = mcrypt_module_open('cast-128', '', 'ecb', ''); /* dado que algunas funciones requieren de un vector de inicializacion acorde con sus especificaciones esta funcin determina el tamao de ese vector atendiendo al tipo de identificador */ $long_iniciador=mcrypt_enc_get_iv_size($ident); /* crea el vector de inicializacin con valores aleatorios y dndole la dimensin precalculada en la funcin anterior */ $inicializador = mcrypt_create_iv ($long_iniciador, MCRYPT_RAND); /* hacemos algunas comprobaciones innecesarias para ejecutar el script. Simplemente son descriptores de algunas funciones complementarias */

/* comprobamos el tamao maximo (en bytes) que puede tener la clave para este algoritmo de cifra*/ print "La clave no puede sobrepasar los "; print mcrypt_enc_get_key_size ($ident)." bytes<br>"; /* escribimos el tamao del bloque del algoritmo que estamos usando*/ print "El tamao del bloque de cifrado es "; print mcrypt_enc_get_block_size($ident)." bytes<br>"; print "El modo de cifrado es "; print mcrypt_enc_get_modes_name($ident)."<br>"; print "El algoritmo de cifrado es "; print mcrypt_enc_get_algorithms_name($ident)."<br>"; print "El tamao del vector de inicializacin es "; print mcrypt_enc_get_iv_size ($ident)."<br>"; /* Contimuamos la secuencia de encriptado incializando todos los buffer necesarios para llevar a cabo las labores de encriptado */ mcrypt_generic_init($ident, $clave, $inicializador); /* realiza el encriptado proopiamente dicho */ $texto_encriptado = mcrypt_generic($ident, $texto); /* libera los buffer pero no cierra el modulo */ mcrypt_generic_deinit($ident); /* esta instruccion es necesaria para cerrar el modulo de encriptado*/ mcrypt_module_close($ident); # imprimimos el resultado de la encriptacin # en este caso aadimos una codificacin de ese resultado en base 64 print "La cadena encriptada es: ".base64_encode ($texto_encriptado); /* guardamos la cadena encriptada en un fichero con nombre encriptado */ file_put_contents('encriptado',$texto_encriptado); print "<br> est codificada en base 64"; ?>
Ejecutar ejemplo de encriptado

El proceso inverso, la desencriptacin de una cadena codificada puede hacerse de la forma que se indica en el siguiente ejemplo.

<?php /* hemos de usar la misma clave con la que ha sido encriptado */ $clave = "clave"; /* leemos el fichero encriptado creado por el script anterior */ $texto_encriptado =file_get_contents('encriptado'); /*creamos un identificador de encriptado que ha de ser el mismo con el que hemos realizado la encriptacin */ $ident = mcrypt_module_open('cast-128', '', 'ecb', ''); /* dado que algunas funciones requieren de un vector de inicializacion acorde con sus especificaciones esta funcin determina el tamao de ese vector atendiendo al tipo de identificador anterior*/ $long_iniciador=mcrypt_enc_get_iv_size($ident); /* crea el vector de inicializacin con valores aleatorios y dndole la dimensin precalculada en la funcin anterior */ $inicializador = mcrypt_create_iv ($long_iniciador, MCRYPT_RAND); /* incializa todos los buffer necesarios para llevar a cabo las labores de encriptado */ mcrypt_generic_init($ident, $clave, $inicializador); /* realiza el desencriptado proopiamente dicho. Realmente es la unica diferencia bsica entre este script y el ejemplo anterior */ $desencriptado = mdecrypt_generic($ident, $texto_encriptado); /* libera los buffer pero no cierra el modulo */ mcrypt_generic_deinit($ident);

/* esta instruccion es necesaria para cerrar el modulo de encriptado*/ mcrypt_module_close($ident); # imprimimos el resultado de la encriptacin # en este caso aadimos una codificacin de ese resultado en base 64 print $desencriptado; ?>
Ejecutar ejemplo de descifrado

Cuidado! Si al intentar ejecutar el ejemplo anterior sobre Ubuntu observas slo una pgina en blanco comprueba que el directorio en el que ests ejecutando el script tenga permisos de lectura/escritura. De no disponer de ellos no se guardara el fichero con los datos encriptados y por es misma razn tampoco se visualizara.

El protocolo de Diffie-Hellman
Una de las debilidades del cifrado con clave simtrica reside en la necesidad de que ambas partes intercambien su clave de cifrado de forma confidencial. Esa confidencialidad puede conseguirse, incluso en comunicaciones de forma no segura, mediante una tcnica conocida como protocolo de Diffie-Hellman.

Nmeros y sus races primitivas


Este protocolo requiere la utilizacin de dos nmeros que llamaremos p y g. El nmero p habr de ser un nmero primo, por lo general muy grande, mientras que g ha de ser una raz primitiva de p. Sin abundar en aspectos demasiado tcnicos podemos decir que g es raiz primitiva de p si el conjunto de los restos de dividir entre p cada de las sucesivas potencias de g desde 1 hasta p1 1 2 3 p-1 1 (g , g , g , g , ... g ) contiene a todos los naturales {1,2,3,4..., p-1}. Eso significara que para cualquier entero b menor que p y una raz primitiva g del nmero primo p, se puede encontrar un nico i exponente ital que b = g (mod p) donde 0 i (p-1). El exponente i se conoce como el logaritmo discreto o ndice de b para la base g, mod p. Este valor se representa como indg,p(b). En la tabla que tienes a continuacin puedes ver el proceso de comprobacin de raices primitivas desarrollado para dos supuestos. Observa que en el caso de g=13 los restos de las divisiones se repiten (lo cual significa que hay valores que no aparecen) y por tanto 13 no es raz primitiva de 23. Por el contrario, al comprobar el comportamiento de g=7 puedes ver los restos son, de forma no ordenada, los nmeros naturales comprendidos entre 1 y 22. Por tanto g=7 si es raz primitiva de 23.

Comprobacin de las races primitivas


z 1 2 3 4 5 6 7 8 9 p=23, g=7 (7 ES raz primitiva de 23) gz 7 49 343 2401 16807 117649 823543 5764801 40353607 Cociente entero gz/p 0 46 322 2392 16790 117645 823538 5764789 40353592 282475236 1977326721 13841287185 96889010387 678223072847 4747561509929 33232930569595 232630513987188 p=23, g=13 (13 NO ES raz primitiva de 23) Resto gz/p gz 7 3 21 9 17 4 5 12 15 13 22 16 20 2 14 6 19 13 169 2197 28561 371293 4826809 62748517 815730721 10604499373 137858491849 1792160394037 23298085122481 302875106592253 3937376385699289 51185893014090757 665416609183179841 8650415919381337933 Cociente entero gz/p 0 161 2185 28543 371289 4826803 62748508 815730719 10604499370 137858491833 1792160394036 23298085122468 302875106592245 3937376385699277 51185893014090739 665416609183179837 8650415919381337927 Resto gz/p 13 8 12 18 4 6 9 2 3 16 1 13 8 12 18 4 6

10 282475249 11 1977326743 12 13841287201 13 96889010407 14 678223072849 15 4747561509943 16 33232930569601 17 232630513987207

18 1628413597910449 19 11398895185373143 20 79792266297612001 21 558545864083284007

1628413597910431 11398895185373132 79792266297611993 558545864083283997

18 11 8 10

112455406951957393129 1461920290375446110677 19004963774880799438801 247064529073450392704413

112455406951957393120 1461920290375446110675 19004963774880799438798 247064529073450392704397

9 2 3 16

22 3909821048582988049 3909821048582988048 1

3211838877954855105157369 3211838877954855105157368 1

Obtencin e intercambio de claves


Intecambiados de forma pblica dos nmeros p y g tales que g es raz primitiva de p, cada uno de los dos usuarios que x y pretenden encontrar una clave comn y secreta genera sendos nmeros XA=g (mod p) y XB=g (mod p) donde x e y son nmeros cualesquiera (secretos, ya que no sern intercambiados), menores que p. Ambos usuarios intercambian sus nmeros. A facilita a B su XA y B proporciona a A el valor XB. Cada usuario eleva a su clave secreta el valor pblico recibido del otro usuario y obtiene el resto de dividir el resultado entre el x y nmero p. Es decir, el usuario A efecta la operacin: KA=(XB) (mod p) mientras que B calcula: Kb=(XA) (mod p). Ambos resultados son iguales dado que se verifica que: KA= (XB) (mod p)= (g ) (mod p)=(g )(mod p), y tambin que: KB= (XA) (mod p)= (g ) (mod p)=(g )(mod p) confirmdonse por tanto que ambos resultados han de ser iguales y que su valor ser la clave simtrica buscada. La prctica imposibilidad de que un tercero pueda obtener la clave radica en el hecho de que para calcularla es necesario conocer, al menos, uno de los nmeros que hemos llamado secretos (x y) y aunque es cierto que pueden ser conocidos XA, XB, p y x g (se transmiten o pueden transmitir de forma no segura) para romper la clave sera preciso buscar la solucin a XA=g (mod p) (logaritmo discreto de XA para la base g mdulo p) tarea de muy alta dificultad (nada resulta imposible) cuando se trata de valores de p muy grandes. En esa dificultad radica precisamente la robustez de este protocolo desarrollado en 1976 por Whitfield Diffie y Martin Hellman. Este es un ejemplo del procedimiento de clculo de una clave de cifrado simtrico mediante el protocolo de Diffie-Hellman.
y x y xy x y x yx

Obtencin de una clave comn y secreta para cifrado simtrico Usuario A Usuario B
Acuerdan, de forma pblica, un nmero y una de sus races primitivas clave y un generador. Establezcamos esos nmeros como:

p=23 y g=7
Elige un nmero natural secreto (puede hacerlo al azar) Elige un nmero natural secreto (puede hacerlo al azar)

9
Eleva g al numero elegido, lo divide entre p y determina el resto de esa divisin

3
Eleva g al numero elegido, lo divide entre p y determina el resto de esa divisin

Resto de 79 entre 23 =15


Enva el nmero anterior a B Eleva el valor recibido (21) a su clave secreta y calcula el resto de dividir ese resultado entre p (23).

Resto de 73 entre 23 =21


Enva el nmero anterior a A Eleva el valor recibido (15) a su clave secreta y calcula el resto de dividir ese resultado entre p (23)

Resto de 219 entre 23=17

Resto de 153 entre 23=17

Ambos obtienen el mismo resultado. Ese valor, solo conocido por ellos, ser la clave de cifrado simtrico La identidad del comunicante como problema de seguridad
Admitiendo la invulnerabilidad (que nunca lo es del todo) del protocolo de Diffie-Hellman y la robustez de los algoritmos de cifrado simtrico tendramos una ms que aceptable seguridad del carcter confidencial (e incluso la integridad) de la informacin intercambiada. Pero queda en el aire una pregunta muy importante. Qu garantas nos ofrecen estas tcnicas de que los comunicantes son los que dicen ser? Quien nos garantiza que no han sido suplantadas sus identidades? Podemos evitar que uno de los comunicantes pueda negar, an habindolo hecho, haber enviado una determinada informacin?. Por el momento la respuesta es no. Sern necesarios otros recursos para solventar ese problema. Tenemos pendiente resolver la autentificacin ( que cada parte de la comunicacin pueda asegurarse de que la otra parte es realmente quien dice ser) y el no repudio (permite a cada uno de los comunicantes probar de forma fehaciente que el otro ha participado en la comunicacin de forma que el remitente

del mensaje no pueda negar haberlo enviado o (caso de no repudio de destino), el destinatario del mensaje no puede negar haberlo recibido. Para resolver esos problemas hemos de recurrir a procedimientos bastante similares a los de la vida cotidiana. Lo primero de todo sera firmar la informacin de la misma forma que se firma un cheque, una carta, un certificado o una solicitud. Esa accin no sera otra cosa que firmar digitalmente nuestros mensajes. Ni en la comunicacin cotidiana ni en la digital resulta de suficiente garanta la firma de un documento. Todos sabemos que puede ser ms o menos hbilmente imitada. La firma manuscrita puede ser falsificada. Necesitamos algn tipo de garanta ms. Cuando en un centro de enseanza se expide un certificado lo habitual es que vaya con la firma del secretario, el visto bueno del director y el sello del centro. Es decir, la firma del director es una garanta de la fidelidad de la del secretario. Puede que no confiemos lo suficiente en la firma del director Autoridad Certificadora y que demandemos la legitimacin notarial de la firma del secretario. La nica diferencia sera el mayor rango de la Autoridad Certificadora. Desde luego siempre podemos seguir desconfiando. De estos asuntos trataremos en los temas siguientes.

Cifrado con clave asimtrica Cifrado asimtrico


El protocolo de Diffie-Hellman que hemos visto en la pgina anterior es un claro ejemplo de lo que se conoce como cifrado asimtrico. A la hora de convenir la clave de cifrado cada uno de los intelocutores utilizaba dos claves. Una de carcter pblico (poda ser conocida sin riesgo) y otro de carcter privado dado que el usuario la mantena en secreto. El primero de los nmeros sera el conocido como clave pblica y el segundo de ellos la clave privada. El cifrado asimtrico, tambin llamado cifrado de clave pblica se fundamenta la utilizacin conjunta de esas dos claves. En el esquema puedes ver las posibilidades que ofrece el uso de este algoritmo en sus dos opciones. Lo cifrado con la clave pblica de un usuario puede ser descifrado con su clave privada. De igual forma, lo cifrado con la clave privada ser descifrado con su clave pblica.

A partir de esas premisas y tal como se ve en el esquema es factible establecer la estrategia para garantizar la confidencialidad y, en cierta medida (hablaremos de esto ms adelante) la autenticidad del remitente.

El algoritmo RSA
El algoritmo de cifrado asimtrico ms popular en este momento es el conocido como RSA (acrnimo de los apellidos de los criptlogos Ronald L. Rivest, Adi Shamir y Leonard Adleman que fueron quienes lo desarrollaron en 1977). La aplicacin de este algoritmo requiere tres pasos:

Generacin de claves
Es un proceso que sigue la siguiente secuencia: Cada usuario elige aleatoriamente dos nmeros primos distintos p y q, pero con longitudes en bits parecidas. La fortaleza de la clave est condiciona en gran medida por el tamao de estos dos nmero que suelen ser muy grandes alcanzando actualmente el 200 orden de 10 y con previsin de aumento de forma simultnea a la capacidad de clculo de los ordenadores. Se calcula el valor n = p*q al que se conocer como mdulo. Se calcula el valor Z=(p-1)*(q-1). Se elige un entero positivo e conocido como exponente de la clave pblica que ha de ser menor que n, que sea coprimo de l. Se determina un valor d, al que se llama exponente de la clave privada, que cumpla a condicin de que d*e (mod Z)=1. Obtenidos esos valores, el par (n,e) ser la clave pblica y (n,d) la clave privada de carcter secreto. Los tamaos habituales de las claves son actualmente de 1024 2048 bits de longitud. En el cuadro que tienes a continuacin intentamos ejemplificar, con valores minsculos, los mecanismos de generacin de claves utilizando este algoritmo.

Algoritmo asimtrico RSA Nmero Ejemplo p 3 q 11 n=p*q 3*11=33 Z=(p-1)*(q-1) (3-1)*(11-1)=20

d Par (n,e) Par (n,d)

Proceso de clculo Primo muy grande. Aleatorio Primo muy grande. Aleatorio Se calcula el producto p*q Producto Calculado Se calcula un nmero que sea: - Primo 7 - Coprimo de Z. Es decir, MCD (e,Z)=1 cumple la condicin - Positivo - <Z 3 Ha de cumplirse que cumple la condicin - d*e (mod Z)=1 Resto de (7*3)/20=1 Par (33,7) Clave pblica- Mdulo y exponente Par (33,3) Clave privada- Mdulo y exponente

Cifrado y descifrado
En este cuadro tienes un ejemplo de funcionamiento del cifrado/descifrado de un nmero. Hablamos de nmeros porque cuando se utiliza este procedimiento las cadenas de caracteres se convierten en bloques numricos (utilizando los cdigos ASCII de los caracteres) agregando al resultado un mtodo de camuflaje conocido como Paddings Schemes que consiste en aadir algunos bits al mensaje de forma que el proceso de cifrado incluya esos bits aadidos que minimizan riesgos de vulnerabilidad de propio proceso.

Cifrado con clave privada y descifrado con clave pblica numero=5 Para cifrar se eleva el nmero a cifrar al valor de la clave privada y se 53(mod 33)= determina el resto de dividir el resultado entre n (numero)d (mod Resto de n) (53)/33=26 53=125; cociente entero 125/33=3; resto de la divisin=26 cifrado=26 ya que: 3*33+26=99+26=125 Para descifrar eleva el nmero cifrado al valor de la clave pblica y se cifrado=26 determina el resto de dividir el resultado entre n 267(mod 33)= e (cifrado) (mod Resto n) 267=8031810176; cociente entero 8031810176/33=243388187; (267)/33=5 resto de la divisin=5 numero=5 ya que: 243388187*33+5=8031810171+5=8031810176 Cifrado con clave pblica y descifrado con clave privada numero=5 Para cifrar se eleva el nmero a cifrar al valor de la clave pblica y se 57(mod 33)= determina el resto de dividir el resultado entre n (numero)e (mod Resto de n) (57)/33=14 57=78125; cociente entero 78125/33=2367; resto de la divisin=14 cifrado=14 ya que: 2367*33+26=78111+14=78125 cifrado=14 Para descifrar eleva el nmero cifrado al valor de la clave privada y se 143(mod 33)= determina el resto de dividir el resultado entre n (cifrado)d (mod Resto de n) (143)/33=5 143=2744; cociente entero 2744/33=83; resto de la divisin=5 numero=5 ya que: 83*33+5=2739+5=2744
Obviamente los ejemplos anteriores no son otra cosa que muestras simplificadas de los procedimientos aritmticos de cifrado y descifrado.

Limitaciones del algoritmo RSA


El cifrado asimtrico presenta algunos problemas operativos tales como: Para una misma longitud de clave y mensaje se necesita mayor tiempo de proceso. Las claves deben ser de mayor tamao que las simtricas
Tabla comparativa de tamaos de claves de similiar resistencia a ataques de fuerza bruta

Simtrica 64 bits 80 bits 112 bits 128 bits

Asimtrica 512 bits 768 bits 1792 bits 2304 bits

Certificados digitales
Certificado digital
Cuando recibimos informacin cifrada con clave asimtrica pueden darse varias situaciones. Entre ellas estas:

Cifrado con nuestra clave pblica

Solo nos garantiza la confidencialidad de la informacin dado que solo nosotros podremos descifrarlo pero nos oculta la verdadera identidad del remitente ya que cualquiera que haya tenido acceso a nuestra clave pblica (cualquier usuario de la red podra haber tenido acceso a ella) pudo haberlo enviado.

Cifrado con clave privada


Tampoco nos garantiza la identidad del remitente. Slo nos asegura que ha sido enviado por la misma persona que nos facilit la clave pblica. Eso no garantiza en ningn modo la identidad. Slo prueba la concordancia entre la clave privada y la clave pblica. Es evidente que se requiere algo ms y eso puede ser un certificado digital.

Qu es un certificado digital?
Es un documento digital mediante el cual un tercero confiable garantiza la vinculacin entre la identidad de un sujeto o entidad y su clave pblica. Podramos considerarlo como algo muy similar al documento nacional de identidad espaol (en otros pases seguramente existe un documento equivalente). El D.N.I. requiere que sea expedido por una entidad confiable (la Direccin General de la Polica) que garantiza que los datos que figuran en l corresponden a la persona fsica cuya fotografa, datos, firma y huella dactilar aparecen impresos.

Tipos de certificado digital


Dependiendo de la informacin que contiene cada uno y la finalidad con la que se emiten existen diferentes tipos de certificado digital. Para nuestro propsito resultan de particular inters:

Certificados personales
Acreditan la identidad del titular que ha de ser una persona fsica. Su finalidad es la firma electrnica de documentos con garantade: la identidad del emisor, el no repudio de origen, la integridad y, si se requiere, la confidencialidad del contenido. Tambin pueden ser usados para la autentificacin de usuarios en sistemas que requieran un control de acceso sustituyendo los clsicos nombre de usuario y contrasea. En Espaa, las muestras ms genuinas de este tipo de certificado son el el DNIe o el CERES - FNMT que emite de forma gratuita a peticin de cualquier ciudadano espaol la Fbrica Nacional de Moneda y Timbre. En el primer caso necesitamos un lector de tarjetas integrado en el propio teclado o accesible a travs de una conexin USB externa el certificado va incluido en el propio DNIE que tiene caractersticas de tarjeta criptogrfica y en el segundo puede obtenerse mediante la descarga de un fichero a travs de internet o adquiriendo en la FNMT una tarjeta criptogrfica que lo contenga.

Certificado de servidor seguro


Son certificados destinados ser instalados en los servidores para asegurar su identidad frente a los usuarios que acceden.Garantizara que el sitio web es el original, que no ha sido suplantado y que nadie ajeno al titular ha podido alterar la informacin publicada. Este tipo de certificados no suelen ser gratuitos son los emitidos por Autoridades Certificadoras (CA) tales como: Verisign, Thawte, RSA Security o GeoTrust por mencionar solo algunos de los ms conocidos internacionalmente. Normalmente su precio vara dependiendo del plazo de validez y del prestigio de la entidad certificadora.

Certificado de autoridad certificadora


Una Autoridad Certificadora (CA) es una entidad en la que confan el emisor y el receptor de una comunicacin. La confianza del emisor y del receptor en ella implica que ambos confan en los documentos firmados por la Autoridad Certificadora de su confianza. Los certificados de estas entidades llamados certificados raz las CA se certifican a si mismas tienen por nica finalidad permitir que sean verificables los certificado de terceros (servidores y/o clientes) expedidos por ella. Suelen tener carcter pblico son descargables como ocurre con el del DNIe.

Emisin de certificados
Tcnicamente resulta sumamente fcil crear certificaciones de todo tipo y tambin convertirse en autoridades de certificacin. El propio PHP dispone de funciones capaces de crear ese tipo de documentos y existen, adems, aplicaciones gratuitas OpenSSL, por citar la herramienta que nosotros vamos a utilizar que realizan la misma funcin en cuestin de muy pocos segundos. El problema est en laconfianza.

Por poner un ejemplo. Cualquiera podra disear un bonito diploma acadmico y emitir ttulos de doctor en Medicina en cualquier mercadillo callejero. Puede que incluso uno de esos ttulos pudiera llegar a manos de un facultativo de acreditadsimo prestigio. El problema sera, desde el punto de vista de la certificacin, que ningn hospital la aceptara como vlida. Estara fracasando la confianza, por un NO reconocimiento de autoridad certificadora. Pongamos un segundo ejemplo. Nadie en Espaa ni en la Comunidad Europea pondra en cuestin nuestra identidad si mostranos nuestro DNI. La autoridad certificada de la Direccin General de la Polica sera reconocida en toda Europa pero tendra la misma validez en China o en USA?. Seguramente no. All solo reconoceran el pasaporte como documento acreditativo de nuestra identidad. De igual forma, una autoridad certificadora (CA) podr tener un mayor o menor reconocimiento (vinculado a las garantas de veracidad y seguridad que ofrece). De ese grado de reconocimiento, entre otras cosas, suele depender el precio. Las CA deben prestar especial atencin a garantizar que nadie ms que ellas pueden realizar su firma. Esa es la razn por la que ha de convertirse en algo casi obsesivo la custodia e inaccesibilidad de su clave privada. Si un tercero pudiera hacerse con ella estara en disposicin de emitir certificaciones falsas con la misma calidad que si permitieran a un falsificador hacer uso de las instalaciones y materiales de la FNMT.

Proceso de firma de un certificado


Cuando un entidad certificadora recibe una peticin de certificado lo procesa de la forma siguiente: Elabora el certificado incluyendo la informacin relativa a solicitante y entidad certificadora. Aplica un algoritmo de hash que no es otra cosa que una funcin matemtica que procesa los datos contenidos en el documento y obtiene a partir de ellos una cadena corta de caracteres huella digital que tiene la peculiaridad de que su valor resultara alterado por la ms mnima modificacin del documento original. Cifra con su clave privada la huella digital y la incluye dentro del certificado del cliente.

Comprobacin de un certificado
Para comprobar la validez de un certificado debemos seguir un proceso inverso al anterior. Se separa la firma digital de la entidad certificadora del documento. A partir de ah, mediante la clave pblica de la entidad certificadora, puede desencriptarse la huella digital contenida en la firma del certificado. Paralelamente se aplica el algoritmo de hash al documento y se determina su huella digital. Si su valor coincide con el extraido de la firma digital ya tendramos la certeza de que el certificado no ha sufrido modificacin alguna. Es un documento autntico.

Por otra parte el descifrado con clave asimtrica de la huella incluida en el certificado nos garantiza que, adems de no haber sido alterado, ha sido firmado realmente por la autoridad certificadora y no por otros. En la pgina siguiente veremos como configurar un servidor seguro y como establecer comunicaciones seguras utilizando este tipo de certificados.

Certificados auto firmados


Vamos a ver el procedimiento de creacin de certificados digitales auto firmados. Para ello disponemos de una aplicacin conocida como OpenSSL que nos va a permitir crearlos sin otra limitacin que nuestro escaso prestigio como Autoridad Certificadora.

Configuracin de OpenSSL
Tanto la versin de Apache que te he sugerido en pginas anteriores como la de nuestra instalacin automtica ya incluyen OpenSSL pero debemos configurar PHP para poder utilizarlo adecuadamente. Bastar con descomentar la lnea 963 del fichero php.ini que tienes en el subdirectorio php53 y donde dice: ;extension=php_openssl.dll quitar el punto y coma, guardar los cambios y reiniciar el servidor Apache. Al acceder a http://localhost/info.php debers visualizar algo como esto:

Si tu sistema operativo es Ubuntu debers instalar primero y habilitar despus el mdulo SSL ejecutando desde la consola los siguientes comandos: sudo apt-get install apache2 libapache-mod-ssl sudo a2enmod ssl

Si eres usuario de Windows habrs de hacer una modificacin en las variables de entorno del sistema. Para ello debes acceder a: Inicio-> Configuracin-> Paneles de control--> Sistema -> (configuracin Avanzada*)-> Opciones avanzadas ->botn Variables de entorno

y comprobar si existe una variable del sistema (parte inferior de la ventana)con nombre OPENSSL_CONF y como valorC:/ServidoresLocales/Apache/conf/openssl.cnf. En caso de que no existiera tendramos que pulsar sobre la opcin Nueva y rellenar una ventana como esta que ves en la imagen:

Una vez hayas pulsado Aceptar debers reiniciar el equipo para que el cambio de configuracin surta efectos.

Cuidado! El valor de la variable del sistema OPENSSL_CONF ha de ser la ruta absoluta hasta el fichero openssl.cnf que se incluye por defecto en directorio conf de Apache cuando se instala la versin que incluye openssl (en nuestro casohttpd-2.2.17-win32-x86-openssl-0.9.8o.msi). El fichero se identifica por su icono (no se visualiza su extensin que es .cnf)

Si eventualmente necesitsemos editarlo habramos de recurrir al shell de la consola de windows y ejecutar el comanto: edit C:/ServidoresLocales/Apache/conf/openssl.cnf

Creacin de certificados digitales


Mediante la aplicacin OpenSSL que suele venir configurada por defecto en la versiones de Ubuntu y cuya versin para Windows puede encontrarse en en este enlace podemos crear nuestros propios certificados digitales desde la consola de Ubuntu o desde el cmd.exe de windows siguiendo un proceso como el que se describe en las diferentes ventanas de esta imagen.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Siguiendo el proceso descrito en la imagen, y para facilitarte la labor hemos incluido aqu un fichero llamado certificados.zip que contiene, entre otros, los siguientes ficheros: CA_privada.key, CA_solicitud.csr, CA_certificado.crt son la clave privada, la solicitud de certificado y el certificado digital autofirmado de una Autoridad Certificadora ficticia creada a modo de ejemplo. Servidor_privada.key, Servidor_solicitud.csr, Servidor_certificado.crt son la clave privada, la solicitud de certificado y el certificado digital de un servidor ficticio. Han sido expedidos por la Autoridad Cerficadora ficticia mencionada en el prrafo anterior. Cliente_privada.key, Cliente_solicitud.csr, Cliente_certificado.crt y Cliente_certificado.p12 son los nombres de los documentos correspondientes a la clave privada, solicitud y certificados digitales expedidos a un usuario ejemplo (cliente) por la Autoridad Cerficadora ficticia. Todos ellos han sido creados siguiendo el proceso descrito grficamente en las imgenes anteriores.

Manejo de certificados digitales de cliente


Una vez dispongamos de un certificado digital de cliente habremos de instalarlo en el navegador de nuestro equipo. En las imgenes se describen los pasos de las diferentes opciones de manejo de este tipo de certificados digitales.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Qu hay dentro de un certificado digital?


Si abrimos el fichero que contiene el certificado de cliente que hemos creado anteriormente nos encontraremos con una cadena de texto resultante de un proceso de codificacin en base 64. Esa informacin es algo ms transparente si recurrimos al uso de la funcin PHPopenssl_x509_parse tal como puedes ver en los ejemplo siguiente:
Certificado original Ver cdigo fuente Contenido certificado Ver cdigo fuente

Podrs observar que contiene (y se puede visualizar) informacin relativa al titular del certificado, perodo de validez, identidad del emisor, etctera. Algo bastante parecido a un DNI tradicional. Hay entre toda la informacin un campo relevante. Observa que hay un valor llamado hash que es la huella digital resultante de aplicar la funcin hash durante proceso de emisin del certificado digital. Es un elemento decisivo para poder comprobar la autenticidad del certificado. Su verificacin ser realizada de forma automtica por el navegador del cliente.

Servidor seguro en Windows


Comunicacin en modo seguro
Una comunicacin en modo seguro mediante el protocolo HTTPS se desencadena de la forma siguiente:

Al iniciarse, por parte del cliente, una sesin (una peticin https://) el navegador enva al servidor un saludo (HELLO) compuesto por una cadena de texto generada de forma aleatoria y la informacin relativa a las versiones de SSL y algoritmos de cifrado que puede soportar. El servidor responde informando de la versin de SSL y mtodo de cifrado aceptados (el ms robusto de los soportados por ambos) y enva otra cadena de texto tambin generada de forma aleatoria. El servidor facilita al cliente su certificado digital y su clave pblica de cifrado. El cliente verifica el certificado digital del servidor y opta por aceptar o rechazar la comunicacin. Cuando el cliente trata de acceder a reas en las que se exige disponer de algn tipo de certificado el servidor le solicita ese certificado digital. Cuando el cliente, atendiendo a un requerimiento del servidor, facilita su certificado digital el servidor inicia un proceso de verificacin de cuyo resultado depende la aceptacin o rechazo la comunicacin. Finalizado de forma favorable el proceso de identificacin el cliente genera una clave aleatoria, la encripta con la clave pblica del servidor y se la enva. El servidor recibe la clave, la desencripta con su llave privada (cifrado asimtrico). Si este proceso resulta fallido ser sntoma de que existe discordancia entre la claves y que no hay certeza de que el servidor sea quien dice ser. Por el contrario, si todo va bien, se confirma la identidad de servidor y contina el proceso El cliente notifica al servidor que, en adelante, toda la informacin que facilite ser encriptada con la clave acordada. Adems, utilizando esa misma clave, encripta una hash (una huella digital) de toda conversacin mantenida hasta el momento y la enva al servidor. Si el servidor puede desencriptar el hash anterior es sntoma de que la clave es correcta y si, adems, el valor de ese hashcoincide con el que crea el servidor con los mismos datos (la informacin intercambiada hasta el momento) se confirma que todo funciona correctamente. Como ltima comprobacin el servidor enva, tambin encriptado con la clave acordada, su hash junto con el aviso de cambio a modo cifrado. El cliente desencripta, compara ambos hash y de resultar coincidentes confirma de forma definitiva que ambos comparten la misma clave (simtrica) y que estn en condiciones de comunicarse en forma segura. Al finalizar la sesin segura se destruye la clave que ambos compartan.

Configuracin del servidor Apache en modo seguro


Area segura del servidor
Es bastante frecuente que los servidores dispongan de dos reas. La zona no segura a la que se accede mediante el protocolo HTTPy la zona segura en la que ser imprescindible utilizar el protocolo HTTPS. Nuestro propsito es que el servidor web tenga una configuracin tradicional no segura en la que el directorio raz seaC:/ServidoresLocales/Apache/htdocs y restringir nicamente a modo seguro el acceso a uno de sus subdirectorios. Para ello, crearemos un subdirectorio de C:/ServidoresLocales/Apache/htdocs ponindole como nombre zona_segura. El paso siguiente ser acceder a http://localhost/info.php y comprobar que tenemos activo el mdulo SSL. Deberemos ver que OpenSSL supportaparece en modo enabled.

Si no lo estuviera deberemos activar ese mdulo tal como se describe en esta pgina.

Certificados de servidor

El primer paso mantener una comunicacin segura es tener la certeza de que realmente estamos en comunicacin con quien pensamos que lo estamos haciendo. Como hemos descrito ms arriba, el protocolo HTTPS requiere con carcter ineludible que el servidor disponga de un certificado digital. Estos certificados puedes extraerlos del fichero certificados.zip o crearlos siguiendo el proceso descrito enesta pgina Una vez dispongamos de los certificados digitales hemos de colocarlos en algn lugar del equipo que alberga el servidor Apache sin que sea en ningn caso necesario ubicarlos dentro del root de servidor. Crearemos un subdirectorio con nombre certificados enC:/ServidoresLocales/Apache/ siendo, por tanto, su ruta absoluta C:/ServidoresLocales/Apache/certificados e incluiremos en l los documentos servidor_certificado.crt (certificado digital del servidor) y Servidor_privada.key (clave privada).

Modificaciones en el fichero httpd.conf


Una vez hayamos creado los directorios zona_segura y certificados e incluido en este el certificado y la clave privada del servidor ya estaremos en disposicin de poder modificar la configuracin del servidor Apache para su uso en modo seguro. Las modificaciones requeridas son las siguientes:

Fichero inicial Guardar como Abrir Lnea

httpd.conf httpd_noseguro.conf httpd.conf


Cambios Donde dice:

La copia de seguridad nos permitir recuperar la configuracin actual si es necesario.

Modificaciones en el fichero inicial Justificacin Con esta modificacin estamos indicando a Apache que escuche las peticiones recibidas tanto a travs del puerto 80 (modo no seguro) como a travs del puerto 443 (utilizado habitualmente para las peticiones en modo seguro). Indicamos a Apache que debe cargar el mdulo SSL que es el que permite tramitar las peticiones de comunicacin en modo seguro.

46

Listen 80 #
cambiar por:

Listen 80 Listen 443


Donde dice:

120

#LoadModule ssl_module modules/mod_ssl.so


cambiar por:

LoadModule ssl_module modules/mod_ssl.so


Agregar:

<Directory "C:/ServidoresLocales/Apache/htdocs/zona_segura"> SSLRequireSSL </Directory>

SSLRequireSSL establece el modo seguro como nico modo de acceso al directorio zona_segura. Cualquier peticin no realizada mediante el protocolo https ser rechazada. NameVirtualHost es una directiva de Apache que permite especificar la IP a travs de la que un host virtual puede recibir las peticiones. Al indicar *:443 estamos sealando como vlida cualquier IP siempre que utilice el puerto 443 que es el reservado para conexiones seguras.

NameVirtualHost *:443

Final del documento

<VirtualHost *:443> SSLEngine On SSLOptions +StdEnvVars +ExportCertData SSLCertificateFile "C:/ServidoresLocales/Apache/certificados/Servidor_certificado.crt" SSLCertificateKeyFile "C:/ServidoresLocales/Apache/certificados/Servidor_privada.key" DocumentRoot "C:/ServidoresLocales/Apache/htdocs/zona_segura" ErrorLog C:/ServidoresLocales/Apache/logs/error.log LogLevel warn </VirtualHost>

Comentamos en la parte inferior de esta tabla los contenidos de estas lneas

Lo contenido entre <VirtualHost> y </VirtualHost> son las directivas que se aplicarn solo al host virtual al que acabamos de aludir. Hemos incluido las siguientes: SSLEngine On que es la directiva que habilita el uso del motor SSL del servidor. SSLOptions es una directiva a travs de la que pueden establecerse condiciones especficas en los directorios a los que precede. Esas condiciones pueden ir

precedidas de un signo + o de un signo -. En el primer caso se entiende que la nueva condicin se agrega a las preexistentes. En el segundo caso, signo menos-, estaramos indicando que se desactive esa condicin manteniendo activas las dems. Activaremos dos de ellas: +StdEnvVars y +ExportCertData. De esta forma podremos leer y utilizar desde PHP la informacin contenida en las variables de entorno del servidor y en los certificados del cliente y del servidor. SSLCertificateFile es una directiva imprescindible para poder indicar la ruta absoluta hasta el certificado del servidor. SSLCertificateKeyFile igual que el anterior, indicando esta la ruta absoluta hasta la clave privada de cifrado del servidor. DocumentRoot especifica la ruta absoluta hasta el directorio que ser considerado como DocumenRoot de este servidor virtual que trabajar en modo seguro. ErrLog especifica la ruta absoluta hasta el fichero que ha de recoger el informes sobre errores producidos durante el funcionamiento del servidor. LogLevel establece los tipos de eventos que van a registrarse como errores. En este caso se registrarn desde advertencias (warn) y/o los errores de mayor gravedad que estas

Una pgina de prueba


Antes de reiniciar el servidor con la nueva configuracin crearemos una pgina de prueba que puede tener unas caractersticas similares a esta.

<?php print "Ests en la zona segura del servidor"; ?>


La guardaremos con nombre index.php en el directorio zona_segura del servidor Apache. Comprobaremos los resultados de intentar acceder a estas direcciones: https://localhost, http://localhost y http://localhost/zona_segura/ En le primer caso (https) estaremos accediendo en modo seguro y por lo tanto seremos dirigidos a la pgina index.php que hemos incluido en el directorio zona_segura que es el DocumentRoot del servidor cuando trabaja en ese modo. En el segundo caso (http) estaremos accediendo en modo no seguro y visualizaremos la pgina index alojada en htdocs (directorio raz del servidor). El tercer supuesto, intento de acceder en modo no seguro (http) a un directorio seguro (zona_segura) nos dar un mensaje de error y nos ser impedido el acceso.

Mensajes de advertencia en los navegadores


Hechas las modificaciones en la configuracin y reiniciado el servidor los intentos de acceso en modo seguro (requiere escribirhttps:// en vez del clsico http:// que los navegadores aaden por defecto) van a aparecernos algunos mensajes de advertencia tales como los que puedes ver en los diferentes apartados de este grfico.
Pulsando sobre la flechas de la imagen podrs visualizar los diferentes pasos del proceso

Formatos de los certificados


Los certificados digitales pueden tener diferentes formatos. Los ms comunes son el formato DER (un formato binario utilizado bsicamente por Java y por Macintosh) y el formato PEM (una representacin de los certificados DER en base64, con marcas de inicio y final). El primero es el formato en el que el Cuerpo Nacional de Polica nos facilita los certificados raz del DNIe cuyos ficheros disponibles puedesver en este enlace de dnde podremos descargar el fichero ACRAIZ-SHA1.zip que vamos a utilizar para la configuracin de nuestro servidor. La FNMT nos permite descargar su certificado raz FNMTClase2CA.cer en ese mismo formato DER. El servidor Apache requiere que los certificados tengan formato PEM (que coincide coun el certificados autofirmados que hemos creado en pginas anteriores. Por tanto nuestros certificados van a poder ser utilizados sin ninguna modificacin por el servidor Apache.

Los certificados emitidos por la Direccin General de la Polica y por la FNMT tienen formato DER y por tanto es preciso hacer un cambio de formato (de DER a PEM) para poder utilizarlos en Apache. La transformacin puede hacerse mediante OpenSSL ejecutando el siguiente comando: openssl x509 -in nombre_del fichero_der -inform DER -out nombre_del_fichero_pem -outform PEM Para facilitarte la tarea hemos incluido en el fichero certificados.zip los certificados raz del DNIe y de la FNMT transformados a formatoPEM por medio de los siguientes comandos: openssl x509 -in ACRAIZ-SHA1.crt -inform DER -out RaizDNIe.crt -outform PEM openssl x509 -in FNMTClase2CA.cer -inform DER -out RaizFNMT.crt -outform PEM Tenemos por tanto los certificados raz de tres entidades certificadoras: nuestra propia CA (CA_certificado.crt, en formato PEM), elDNIe (ACRAIZ-SHA1.crt, en formato DER, y su equivalente en formato PEM, RaizDNIe.crt) y la FNMT (FNMTClase2CA.cer en formato DER y su equivalente en formato PEM, RaizFNMT.crt)

Accesos restringidos
Podemos establecer conexiones en modo seguro con un servidor si que se nos exija cumplir ningn requisito. El concepto seguro significara que el servidor posee un certificado digital y que la informacin circula encriptada mediante una clave simtrica pero desconociendo la identidad del cliente. Son habituales las webs que requieren un registro previo del usuario en el que se le facilita un nombre de usuario y contrasea que le sern requeridas siempre que intente acceder a un rea restringida del servidor. Disponiendo de un servidor seguro es posible exigir al cliente que disponga de un certificado digital (certificado de cliente) para acceder al rea segura del servidor o algunos de sus directorios. Veamos como hacerlo. Empezaremos creando un subdirectorio de zona_segura al que pondremos el nombre de restringido e incluiremos en l una pgina, a la que llamaremos index.php, que nos permita hacer la comprobacin de funcionamiento y que puede contener algo como esto:

<?php print "Aqu solo acceden los usuarios autorizados"; ?>


Nuestro propsito es que slo puedan acceder acceder al directorio restringido los cliente que dispongan de: nuestro certificado autofirmado de pruebas, de un DNIe o de un certificado de la FNMT. Establecer esa exigencia nos obliga a configurar Apache de forma que sepa qu ha de requerir un certificado de cliente y, adems,qu tipo o tipos de certificados debe considerar vlidos. Esto se logra a travs de la directiva SSLCACertificateFile que debe ir seguida de la ruta absoluta hasta un nico fichero que ha de contener el certificado o certificados raz de las entidades certificadoras a cuyos usuarios se va a permitir el acceso. En el epgrafe anterior hemos visto como obtener, en formato PEM, los tres certificados (CA_certificado.crt, RaizDNIe.crt yRaizFNMT.crt). Hemos de juntarlos en un nico fichero. Para ello podemos crear un fichero nuevo en blanco (con Notepad++, el bloc de notas o cualquier otro editor de tu eleccin) e ir incluyendo en l, uno tras de otro, los contenidos de los tres ficheros anteriores. Una vez guardemos el fichero resultante podemos ponerle como nombre todos.crt en el almacn de certificados del servidor (C:/ServidoresLocales/Apache/certificados) ya solo nos faltara modificar el fichero de configuracin de Apache para que contemple la nueva situacin. La modificaciones a realizar son las que puedes ver en esta tabla

Fichero inicial Guardar como Abrir

httpd.conf http_seguroparcial.conf
Nos permitir recuperar la configuracin actual si es necesario

httpd.conf
Trabajaremos sobre la configuracin previa una vez asegurada una copia de ella Donde dice:

Modificaciones en el fichero inicial

SSLCertificateKeyFile "C:/ServidoresLocales/Apache/certificados/Servidor_privada.key""
insertar inmediatamente despus

SSLCACertificateFile "C:/ServidoresLocales/Apache/certificados/todos.crt"

Agregar inmediatamente antes de la etiqueta de cierre </VirtualHost> que hay al final del fichero :

Final del documento

<Directory "C:/ServidoresLocales/Apache/htdocs/zona_segura/restringido"> SSLVerifyClient require SSLVerifyDepth 2 SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0") </Directory>

Se trata de sealar la existencia un fichero con los certificados raz de las entidades certificadoras autorizadas mediante la directivaSSLCACertificateFile seguida de la ruta absoluta hasta el fichero que contiene tales certificados y de indicar qu directorio debe restringirse y cuales son las condiciones de acceso. Esto se indica en el contexto de las etiquetas <Directory > y </Directory >. Dentro de la etiqueta de apertura indicamos la ruta absoluta del directorio objeto de la restriccin (en este caso ser restringido) y entre la etiqueta de apertura y cierre incluimos las restantes directivas. Mediante el valor require de la directiva SSLVerifyClient Apache interpretar que debe exigir uno de los certificados de usuario permitidos para acceder al directorio en el que se incluye tal directiva. Si esta directiva no se incluyera entre las etiquetas <Directory></Directory> se entendera que la directiva habra de afectar a todo el espacio del servidor seguro. Con las modificaciones anteriores el servidor ya debera funcionar de acuerdo con nuestros propsitos. Sin embargo, si observas con detenimiento las propuestas de modificaciones, vers que hemos incluido la directiva SSLVerifyDepth 2. Esto es consecuencia de la inclusin de la opcin DNIe. La Autoridad de Certificacin de Primer Nivel de la Direccin General de la Polica slo emite certificados para s misma y para sus tres autoridades certificadoras subordinadas. Por tanto, ninguno de los certificados incluidos en los DNie es emitido por la Autoridad Certificadora de primer nivel. Quien certifica nuestro DNIe es una de las tres entidades subordinadas (segundo nivel) que dependen de aquella. Por medio de la directiva SSLVerifyDepth 2 lo que hacemos es indicarle a Apache que, si es necesario, profundice hasta ese segundo nivel para comprobar la validez del certificado del cliente. Aunque es un aspecto que ser comentado con un poco ms de profundidad en prrafos suguientes, la lnea dnde dice SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0") tiene como finalidad que Apache impida el acceso a usuarios cuyos certificados del cliente han superado su perodo de validez (qu han caducado). Hechas estas modificaciones y reiniciado Apache podremos comprobar que para acceder a la direccin https://localhost" no es preciso disponer de ningn certificado. Por el contrario, si pretendemos acceder a https://localhost/restringido/ nos ser requerido uno cualquiera de estos tres certificados: nuestro certificado autofirmado, un certificado de la FNMT el DNIe.

Condicionando las restricciones


En la configuracin anterior establecimos como nica condicin para el acceso al directorio restringido disponer de uno de los certificados permitidos y que este no hubiera expirado (un poco ms abajo comentamos la directiva SSLRequire que es la que hace esta comprobacin). Vamos a crear ahora dos nuevos subdirectorios en la zona_segura. A uno le llamaremos dnie y al otro certificado. Incluiremos en cada uno de ellos, una pgina con nombre index.php para hacer las pruebas de funcionamiento. El acceso al primero dnie lo limitaremos a los usuarios que dispongan de un DNIe o un certificado de la FNMT e impediremos que pueda hacerlo quien slo disponga del certificado autofirmado creado para nuestros ejemplos. Para el acceso al directorio certificado invertiremos las condiciones. Slo estar permitido el acceso autentificndose mediante el certificado autofirmado. Dado que en el fichero todos.crt estn incluidos los certificados raz de las tres entidades certificadoras permitidas, las nuevas limitaciones requieren hacer uso de la directiva SSLRequire. Veamos que ocurre con ella. Cuando hacemos una peticin en modo seguro y la directiva SSLOptions est configurada +StdEnvVars se transfieren al servidor una serie de variables de entorno cuyos nombres y valores para cada uno de los tres tipos de certificado (lgicamente con datos ficticios) puedes ver en este enlace:
Variables de entorno

Los valores que se visualizan en este ejemplo son el resumen de la comprobacin de los tres tipos de certificados digitales y han sido obtenidos desde PHP mediante funciones similares a esta: <?php print getenv('SSL_CLIENT_S_DN');?> dnde a la funcin getenv se el incluye como parmetro el nombre de una variable de entorno. Aqu tienes el cdigo fuente del script que hemos utilizado para leer todas esas variables (https) y la lista de sus nombres.

Si observamos con un poco de detenimiento la tabla del enlace anterior podremos ver que hay una variable de entorno llamadaSSL_CLIENT_V_REMAIN que recoge los das que faltan hasta la fecha de caducidad de cada uno de los certificados. Tambin podemos ver como SSL_CLIENT_I_DN_OU recoge los valores: certNORA, FNMT Clase 2 CA y DNIE y que en SSL_CLIENT_I_DN_Ose incluyen: ACREDITACIONES DEL NORA, S.L.U., FNMT y DIRECCION GENERAL DE LA POLICIA. Mediante la directiva SSLRequire y manejando esas variables, a las que se alude mediante la sintaxis %{nombre de la variable} , los operadores lgicos and y/o or (en minsculas porque SSLRequire es sensible a maysculas/minsculas) y los operadores de comparacin== (o su equivalente eq), <, > podemos establecer las condiciones requeridas para el acceso a un directorio determinado. Analicemos este ejemplo. SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \ and (%{SSL_CLIENT_I_DN_O} eq "FNMT" or %{SSL_CLIENT_I_DN_OU} == "DNIE")) SSLRequire() incluye, dentro del parntesis, las condiciones restriccitivas que son las siguientes: %{SSL_CLIENT_V_REMAIN} >= "0"que exige que el certificado no haya expirado con anterioridad a la fecha (le quede un nmero de das de vigencia mayor o igual que cero). Aunque se trate de un valor nmerico el cero lo pondremos entre comillas. La barra invertida (\) es un carcter imprescindible para indicar que el condicionado contina en la lnea siguiente y el operador andagrega como nueva condicin que %{SSL_CLIENT_I_DN_O} eq "FNMT" or %{SSL_CLIENT_I_DN_OU}=="DNIE" lo cual significa la exigencia de que solo sern admisibles certificados en los que SSL_CLIENT_I_DN_O="FNMT" o aquellos en los que SSL_CLIENT_I_DN_OU="DNIE". De esta forma, las ltimas modificaciones de la configuracin de Apache, seran las siguientes:

Fichero inicial Guardar como Abrir

httpd.conf httpd_seguro_parcial_1.conf
Nos permitir recuperar la configuracin actual si es necesario

httpd.conf
Trabajaremos sobre la configuracin previa una vez asegurada una copia de ella Agregar inmediatamente antes de la etiqueta de cierre </VirtualHost> que hay al final del fichero :

Modificaciones en el fichero inicial

Final del documento

<Directory "C:/ServidoresLocales/Apache/htdocs/zona_segura/dnie"> SSLVerifyClient require SSLVerifyDepth 2 SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \ and (%{SSL_CLIENT_I_DN_O} eq "FNMT" \ or %{SSL_CLIENT_I_DN_OU} == "DNIE")) ErrorDocument 403 https://localhost/error_dnie.html </Directory> <Directory "C:/ServidoresLocales/Apache/htdocs/zona_segura/certificado"> SSLVerifyClient require SSLVerifyDepth 2 SSLRequire (%{SSL_CLIENT_V_REMAIN} >= "0" \ and %{SSL_CLIENT_I_DN_OU} =="certNORA") ErrorDocument 403 https://localhost/error_certificado.html </Directory>

Las lneas ErrorDocument tienen por finalidad redirigir el navegador hacia una pgina de error cuando intentemos acceder a un directorio restringido sin cumplir los requisitos exigidos para ello. Una vez hayas reiniciado el servidor despus de finalizar la configuracin podrs comprobar el funcionamiento accediendo a las direcciones: https://localhost, http://localhost y http://localhost/zona_segura/ Para acceder la primera de ellas necesitars uno de los tres certificados. El segundo requiere disponer de DNIe o un certificado de la FNMT y al tercero podrs acceder si tienes instalado en tu navegador el certificado auto firmado de cliente.

Extraer informacin de certificados Validez de los certificados


Las comprobaciones que se realizan sobre los certificados de usuarios presentan una laguna importante. La validez nos indica que un certificado de DNIe no ha sido manipulado y que ha sido emitido por la polica pero no podemos saber si est siendo usado de modo indebido por el titular o por una tercera persona. Supongamos que perdemos nuestro DNIe, o que simulamos su extravo. En el momento de formular la denuncia, la autoridad gubernativa procede a revocar nuestro certificado digital incorporndolo a la base de datos pblica de documentos revocados. Podramos entender que a partir de ese momento no somos responsables del uso que pueda hacerse del mismo. Para consultar esa base de datos existe un protocolo conocido como OCSP (Online Certificate Status Protocol) mediante el cual podemos conocer la validez actual de un certificado. Estos servicios de validacin del DNIe, segn informan en su web, son prestados de forma ininterrumpida todos los das del ao por la Fbrica Nacional de Moneda y Timbre Real Casa de la Moneda, que prestar sus servicios de validacin con carcter universal: ciudadanos, empresas ... No ocurre lo mismo con los certificados FNMT ya que en ese caso el acceso al OCSP responder no tiene carcter gratuito. Ms abajo tienes un ejemplo de la forma de efectuar la comprobacin de la validez del DNIe y, adems, podrs ver la forma en la que pueden extraerse los datos personales: nombre, apellidos, n, periodo de validez e incluso la fecha de nacimiento del titular. Da la impresin de que en un futuro no muy lejano la autentificacin, e incluso la restriccin de accesos a menores, acabar hacindose mediante este documento.

Lectura de certificados de cliente


PHP dispone de la funcin openssl_x509_parse(certificado, booleano) que permite leer los contenidos de un certificado en formatoPEM y recoger los resultados en un array. Cuando el parmetro booleano es TRUE -valor por defecto- utilizar nombres cortos para los ndices de los arrays. Si a ese parmetro le asignamos el valor FALSE (0) usara nombres largos. La diferencia puedes verla en estos ejemplos. Estos primeros utilizan la opcin FALSE
lee certNORA leee FNMT lee DNIe

mientras que estos otros utilizan la opcin TRUE. En ambos caso estamos visualizando copias de los tres tipos de certificados: nuestros certificados de prueba, un certificado de la FNMT y otro de DNIe.
lee certNORA leee FNMT lee DNIe

Para que puedas visualizar estos certificados ejemplo tienen carcter pblico y no pueden ser utilizados sin su clave privada hemos guardado aqu una copia de ellos. Cuando intentamos acceder, mediante el protocolo HTTPS a un directorio configurado como SSLVerifyClient require y, adems se incluye la opcin SSLOptions +ExportCertData los datos de los certificados de servidor y cliente son recogidos en dos variables superglobales. La variable $_SERVER['SSL_SERVER_CERT'] contendr una cadena con el certificado del servidor en formato PEM mientras que$_SERVER['SSL_CLIENT_CERT'] tendr idntica informacin pero referente al certificado del cliente. Este es el cdigo fuente del script utilizado en los ejemplos anteriores.
ver cdigo fuente

Verificacin de la validez de un DNIe


OpenSSL dispone de una utilidad que permite verificar la validez de un DNIe. Se tratara de ejecutar desde la lnea de comando lo siguiente: openssl ocsp -CAfile cert_raiz_dnie -issuer emisor -cert cliente -url direccion cuyos parmetros son los siguientes:

cert_raiz_dnie es la ruta completa y el nombre del fichero (en formato PEM) que contiene el certificado raz del DNIe. emisor es la ruta completa y el nombre de un fichero que contiene los datos del emisor del certificado de DNIe. Se extrae de este documento. cliente es la ruta completa y el nombre de un fichero que contiene los datos del cliente extraidos del DNIe (se extrae de este documento. direccion es la direccin que permite hacer la comprobacin. En el caso del DNIe sera http://ocsp.dnie.es Este comando puede ser ejecutado desde PHP incluyndolo en una llamada a la funcion shell_exec() que es el procedimiento que seguimos en el ejemplo que tienes a continuacin. Al ver el cdigo fuente podrs observar que al script le hemos incluido una opcin para simular la lectura de un DNIe sin necesidad de que configures tu servidor en modo seguro y, a la vez, para intentar ilustrar las posibilidades del DNIe y el certificado de la FNMT en el caso en que no dispongas de ellos o no te apetezca configurar tu servidor para trabajar en modo seguro. Para utilizar este script con tu propio DNIe bastar con que lo copies al directorio restringido de la configuracin que hemos propuesto para el servidor seguro (obviamente es imprescindible esa configuracin) y que accedas a l a travs de la direccin:https://localhost/dnie/test_dnie.php.
Verificar DNIe Ver cdigo fuente

Cuidado! Si has hecho la verificacin del DNIe del ejemplo anterior habrs podido ver que el certificado est revocado. Eso es cierto. El certificado que hemos utilizado corresponde a un DNIe que ya fu renovado y como consecuencia de esa renovacin ha sido emitido un nuevo certificado con la consiguiente revocacin del anterior.

Cmo utilizar el DNIe?


La utilizacin del DNIe electrnico requiere, tal como se explica en su pgina oficial, disponer de un lector de tarjetas inteligentes que cumpla el estndar ISO-7816. Existen distintas implementaciones, bien integrados en el teclado, bien externos (conectados va USB) o bien a travs de una interfaz PCMCIA el uso de un lector. Adems del dispositivo de hardware es necesario realizar algunas instalaciones de certificados y modificar algunas configuraciones de los navegadores. Este proceso puede hacerse basndose en la informacin de la web oficial del DNIe o recurriendo a algunas herramientas que permiten efectuar esa instalacin y configuracin de forma automtica. Una de ellas, https://zonatic.usatudni.es nos permite descargar paquetes autoinstaladores tanto para las diferentes versiones de Windows como para Ubuntu. Para este ltimo caso, en enlace anterior an no dispone en esta fecha (03.04.2012) de una versin que permita realizar la instalacin sobre Ubuntu 12.04. Para quien necesite utilizar esta versin del sistema operativo hay una excelente pgina http://bitplanet.es/manuales/3-linux/ dnde se describe de forma minuciosa todo el proceso de instalacin y configuracin en este supuesto.

Pginas WEB dinmicas


Servidores y clientes
Es frecuente observar, en la calle, que son muchas las personas que cuando se refieren a los servidores lo hacen como s se tratara de mquinas complejsimas, misteriosas, lejanas y enormes que, bajo esa aureola de cripticismo, parecen totalmente distintas al ordenador que usamos habitualmente. Nada ms lejos de la realidad! Vamos a intentar aclarar algunos conceptos con ejemplos cotidianos. Pensemos en esos ordenadores remotos (tambin llamados host) como si se tratara de uno esos sitios desde los que se sirven comidas a domicilio.

Quiz lo primero en lo que se te ocurra pensar sea en una pizza, no porque desconozcas que tambin es posible comprar otras cosas sino por la popularidad de ese tipo de servicio. Algo similar ocurre con los host. La frecuencia con la que accedemos a ellos en demanda de pginas web hace que tendamos a identificarlos con ellas, pero tambin los host ofrecen o pueden ofrecer ms servicios. Sigamos con las comidas a domicilio. Cada una de esas empresas puede atender peticiones de uno solo o de varios servicios distintos (pizzas, helados, o platos regionales, por citar algunos ejemplos), pero la oferta de cada uno de esos servicios requiere una infraestructura adecuada a cada caso. La oferta de pizzas exigir disponer de un horno, y la de helados necesitar de una instalacin frigorfica. Pues bien, algo muy similar ocurre con los host. Tambin stos pueden ofrecer uno o varios servicios (pginas web, correo electrnico, transferencias FTP, noticias, etctera) y tambin es necesario que cada servicio disponga de su propia infraestructura, que en este caso sera un programa distinto (software de servidor) para cada uno de ellos. Como puedes ver, no basta con hablar de servidores. Es necesario especificar tambin qu es lo que sirven.Habra que decir: servidor de pginas web, servidor de correo, etctera y tener presente que aunque convivan en la misma mquina cada uno de ellos requiere su propio software y su propia configuracin. Resumiendo, cuando en lenguaje coloquial hablamos de un servidor estamos aludiendo un host (ordenador remoto) el tamao y la lejana carecen de importancia provisto de programas (software de servidor) que, cuando est accesible (conectado a Internet) y con el software activo (servidor en funcionamiento) es capaz de atender peticiones y devolver a los clientes los documentos solicitados, o un mensaje de error, en el caso de que no estuvieran disponibles. Veamos un ejemplo de cmo se desarrolla ese proceso de peticinrespuesta. Para leer el correo electrnico necesitas disponer de un programa supongamos que es Outlook Express instalado en tu ordenador y hacer, a travs de l, una peticin a un ordenador remoto (host). Si quisieras visualizar pginas web tendras que utilizar un programa distinto Firefox o Internet Explorer, por ejemplo capaz de realizar esta otra tarea. Al programa que utilizamos para realizar cada peticin le llamaremos cliente.

Qu es una peticin?
Una peticin es un conjunto de datos que un cliente (recuerda que el cliente siempre es uno de los programas instalados en tu ordenador) enva a travs de Internet solicitando una respuesta determinada por parte de un servidor (ordenador remoto).

Qu contendra esa peticin?


Cada tipo de peticin tendr contenidos distintos. Por ejemplo, cuando se trata de leer mensajes de correo, la peticin realizada por el cliente (Outlook Express) contendra, entre otros, muchos de los datos de la configuracin de la cuenta, tales como: el protocolo (forma de comunicacin) en el caso del correo lo habitual sera el protocolo POP (Post Office Protocol), el nombre de host donde est alojado el buzn (servidor POP servidor de correo entrante), el nombre de la cuenta, la contrasea de acceso, y algunas otras informaciones relativas a la gestin de esa cuenta tales como si deben conservarse o no los mensajes en el servidor, etctera.

Qu ocurre con esa peticin?


Cualquier peticin pasa en primera instancia por un servidor de nombres de dominio (Domain Name Server) DNS, una especie de gua telefnica que contiene los nombres de los servidores y las direcciones IP a travs de las cuales estn conectados a Internet. Podra decirnos los datos son ficticios que olmo.cnice.mecd.es es el nombre de un host que est conectado a Internet a travs de la direccin IP 111.112.113.114 Una vez resuelta esa peticin por el servidor DNS (direccionamiento de la peticin a la IP correspondiente) se comprobar si esa IP est activa (si efectivamente hay un ordenador conectado a travs de ella) y, en caso de estarlo, se determinar si ese ordenador al que estamos accediendo es capaz de atender la peticin.

Qu tiene que ocurrir para que pueda atenderse una peticin?


Es necesario que el ordenador remoto tenga instalado y funcionando el software de servidor adecuado al protocolo de nuestra peticin. Ello quiere decir siguiendo con el ejemplo que el ordenador remoto debe tener instalado y funcionando un software especfico de servidor de correo capaz de interpretar el protocolo POP3 especificado en la peticin.

Cuidado!

El ordenador remoto debe tener instalado y funcionando el software adecuado a cada tipo de peticin (servicio) que deba atender. No basta con decir servidor, es preciso conocer los servicios que presta y es factible que un mismo ordenador preste simultneamente varios servicios, siempre que tenga instalado y activo el software especfico para cada uno de esos servicios.

Cuando el ordenador remoto acepta la peticin el software de servidor y/o las aplicaciones del lado del servidor (software instalado en el ordenador remoto y vinculado con el software de servidor) resuelven la peticin (comprobar que el nombre de la cuenta y la contrasea son correctas, comprobar si existen mensajes, borrarlos del buzn si as lo especifica la peticin, etc.) y devuelven al cliente (recuerda que el cliente era nuestro Outlook Express) la informacin requerida. Solo falta que una vez recibida la respuesta Outlook Express (cliente) interprete la informacin recibida y nos permita visualizar o imprimir el contenido de los mensajes descargados del servidor.

Servidor y cliente en una misma mquina


Hasta ahora al referirnos a servidores y clientes hemos hecho alusin a dos mquinas: nuestro propio ordenador (ordenador local) en el que estaran instaladas las aplicaciones cliente y un ordenador remoto en el que se alojaran las aplicaciones de servidor. Eso es lo ms habitual, pero no es la nica posibilidad. Dado que servidor y cliente son nicamente aplicaciones, es perfectamente posible que ambas convivan dentro de la misma mquina. La diferencia sustancial sera que ahora no es necesario el servidor de DNS para buscar la direccin IP. Utilizaramos una IP (habitualmente la 127.0.0.1) reservada para estos casos preestablecida en la configuracin del servidor y a travs de ella se canalizaran las peticiones a nuestro propio servidor. Ya hablaremos ms adelante de esta IP.

Tipos de pginas web


Una de las clasificaciones ms simples de las pginas web permitira agruparlas en dos tipos: estticas y dinmicas.

Pginas web estticas


Diremos que una pgina web es esttica cuando sus contenidos no son susceptibles de ser modificados ni por intervencin del usuario ni por una accin automtica del servidor (ordenador remoto) ni del cliente (navegador).

Un ejemplo de pgina esttica


Cualquier usuario que acceda a esta pgina que incluimos como ejemplo ya sea en modo local, o a travs de un servidor remoto visualizar siempre la misma fecha: 22 de setiembre de 2011.

<html> <head> </head> <body> Hoy es 22-09-2011 y son las 11:23:37 horas </body> </html>
ejemplo1.html

Las peticiones de pginas estticas se realizan de la forma que puedes ver en este esquema.

Si observas con detenimiento el esquema de la parte superior es posible que encuentres algo que no te cuadre... porque en el esquema hay un servidor que parece imprescindible para atender las peticiones y sin embargo t sin tener instalado ningn servidor eres capaz de visualizar tus propias pginas web sin ms hacer un doble clic sobre su icono. Eso es cierto, pero fjate en las dos direcciones que aparecen en esta otra imagen.

La de la izquierda consecuencia de haber hecho doble clic sobre el icono del documento contiene como direccin una ruta (el path que conduce hasta el documento) mientras que en la de la derecha aparece el sintagma http al principio de la direccin. En el primer caso no hemos hecho ninguna peticin de pgina web sino que hemos abierto un documento cuya extensin (html) est asociada en nuestra configuracin de Windows con Firefox, Internet Explorer, Opera o cualquier otro navegador que

tengamos instalado en nuestro equipo. El proceso ha sido exactamente el mismo que si hubiramos hecho doble clic sobre el icono de un documento con extensintxt, con la nica salvedad de que en este ltimo caso se habra abierto el bloc de notas (por la asociacin de extensiones y aplicaciones en la configuracin de Windows). En el segundo caso las cosas son distintas. Se incluye el sintagma http acrnimo de HiperText Transfer Protocol para indicar que ese es el protocolo que debe ser utilizado y que ser preciso que el servidor que reciba la peticin sea capaz de interpretarlo. Por eso a los servidores que alojan pginas web se les suele llamar servidores web o servidores HTTP dado que se les requiere que soporten este protocolo.

Pginas dinmicas
Llamaremos dinmicas a las pginas cuyos contenidos s pueden ser modificados de forma automtica o mediante la intervencin de un usuario bien sea desde el cliente y/o desde el servidor. Para que una modificacin de este tipo pueda producirse es necesario que algo o alguien especifique: qu, cmo, cundo, dnde y de qu forma debe hacerse el cambio, y que exista otro algo o alguien capaz de: acceder, interpretar y realizar, en el momento preciso, las instrucciones de modificacin. Igual que ocurre en el contexto de la vida cotidiana, las especificaciones y las instrucciones precisan de un lenguaje para poder definirlas, un soporte para almacenarlas, y un intrprete capaz de ejecutarlas. Somos capaces de entender unas instrucciones escritas en castellano pero si estuvieran escritas en blgaro las cosas seguramente seran bastante distintas, y, por supuesto, a un blgar@ le pasara justamente lo contrario. Igual ocurre con los programas intrpretes de los lenguajes de script. Ellos tambin requieren rdenes escritas en su propio idioma.

Scripts
Se llama script a un conjunto de instrucciones, escritas en un lenguaje determinado, que van incrustadas dentro de una pgina WEB de modo que su intrprete pueda acceder a ellas en el momento en el que se requiera su ejecucin. Cuando se incrustan scripts en una pgina WEB empiezan a convivir dentro de un mismo documento informaciones destinadas a distintos intrpretes. Por una parte, el cdigo HTML que ha de ser interpretado por el navegador, y por la otra, los scripts que han de ser ejecutados por el intrprete propio del lenguaje en el que hayan sido escritos. La manera de diferenciar los contenidos es delimitar los scripts marcando su comienzo con una etiqueta de apertura <script> y sealando el final con una etiqueta de cierre </script>. Lo que no est contenido entre esas etiquetas ser considerado cdigo HTML. La posibilidad de insertar en un mismo documento scripts escritos en distintos lenguajes obliga a especificar cul se ha utilizado en cada caso, para que en el momento en el que vayan a ser ejecutados se invoque el intrprete adecuado. Para ello, dentro de la propia etiqueta de apertura (<script>) se inserta una referencia al tipo de lenguaje con esta sintaxis:language="nombre" Por ejemplo: <script language="PHP"> ...... ...... instrucciones .. ...... </script> indicara que las instrucciones estn escritas con la sintaxis de PHP. Por el contrario, al escribir: <script language="JavaScript"> ...... ...... instrucciones .. ...... </script> estaramos sealando que en las instrucciones contenidas en el script utilizan sintaxis de JavaScript. La alternativa ms reciente (la anterior est obsoleta) sera:<script type="text/javascript">

Para el caso concreto de PHP, existe una sintaxis alternativa, mucho ms cmoda y habitual. Es la siguiente: <?php ...... ......instrucciones.. ...... ?> Aqu <?php har la misma funcin que <script language="PHP"> y ?> ser equivalente a </script>. Con la configuracin adecuada tambin podramos usar <? en vez de <?php como marca inicial.

Lenguajes de script
Hay mltiples posibilidades en cuanto a lenguajes de script. Pero antes de hacer mencin a algunos de ellos es conveniente hacer una clasificacin previa. Hablaremos de dos tipos:lenguajes del lado del cliente y lenguajes del lado del servidor.

Lenguajes del lado del cliente


Diremos que un lenguaje es del lado del cliente cuando el intrprete que ha de ejecutar sus scripts es accesible desde ste el cliente sin que sea necesaria ninguna intervencin en este sentido por parte servidor. Seguramente te ha ocurrido alguna vez que al intentar acceder a una pgina web ha aparecido un mensaje advirtiendo que para la correcta visualizacin de la pgina se requiere un plug-in determinado, y que, a la vez, se te haya ofrecido la posibilidad de descargarlo en ese momento. Eso ocurre porque cuando el navegador que en el caso de las pginas web es el cliente trata de interpretar la pgina, encuentra incrustado en ella algo (un fichero de sonido, una animacin Flash, etctera) que de forma muy similar a lo que ocurre con los scripts requiere un intrprete adecuado del que no dispone en ese momento. Cuando los scripts contenidos en un documento son de este tipo, el servidor lo entrega al cliente si efectuar ningn tipo de modificacin. Sin pretender hacer una enumeracin exhaustiva, entre los lenguajes de script del lado del cliente los ms populares son: DHTML,JavaScript y VBScript. DHTML no es exactamente un lenguaje de programacin. Se trata ms bien de una serie de capacidades que se han ido aadiendo a los navegadores modernos mediante las cuales las pginas pueden contener hojas de estilo y/o organizarse en capas susceptibles de ser modificadas, redimensionadas, desplazadas y/o ocultadas. JavaScript es uno de los lenguajes ms populares. Cada navegador incluye su propio intrprete y es frecuente que los resultados de visualizacin sean algo distintos segn el navegador y la versin que se utilice. Parece ser que las versiones ms recientes de los distintos navegadores se aproximan a un estndar ECMA Script-262 que ha sido desarrollado por la ECMA (Asociacin Europea de Normalizacin de Sistemas de Informacin y Comunicacin), lo que hace suponer que en un futuro muy prximo todos los navegadores se ajustarn a esa especificacin y que, con ello, las pginas web ya se visualizarn de forma idntica en todos ellos. VBScript es un lenguaje de script derivado de VisualBasic y diseado por Microsoft para Internet Explorer y los navegadores derivados o vinculados a este. Una peticin de pgina en la que hay incrustados scripts escritos en lenguaje del lado del cliente se realizara de una forma similar a esta:

Como puedes observar no requiere nada distinto a lo del supuesto anterior. La diferencia sera que en este caso se haran llamadas al intrprete de JavaScript incluido en los navegadores, tal como comentamos al margen y/o a eventuales plugins necesarios para interpretar otros tipos de script. Aqu tienes dos ejemplos de pginas web dinmicas. Ambas utilizan los JavaScript que puedes ver en rojo en su cdigo fuente. Si pulsas en el enlace del primero de estos dos ejemplos vers que la fecha que aparece en la pgina es la fecha actual de tu sistema, y adems, cada vez que pulses el botn Actualizar de tu navegador comprobars que esa intervencin del usuario modifica los contenidos actualizando la hora que aparece en el documento.

<html> <head> <script type="text/javaScript"> var son= new Date(); var fecha=son.getDate()+" - "+(son.getMonth()+1)+" - "+son.getFullYear(); var hora=son.getHours()+":"+son.getMinutes()+":"+son.getSeconds(); document.write('Hoy es '+fecha+' y son las '+hora+' horas'); </script> </head> <body> </body> </html>
ejemplo2.html

En este otro ejemplo la modificacin de los contenidos no requiere intervencin alguna por parte del usuario. Cada 5 segundos (fjate donde dice var frecuencia=5000). Cinco mil es el perodo de actualizacin, expresado en milisegundos) se rescribirn de forma automtica la fecha y la hora. Tenemos por tanto una especie de cronmetro automtico.

<html> <head> <script type="text/javaScript"> var reloj=0; var frecuencia=5000; function actualiza(){

var son= new Date(); var fecha=son.getDate()+" - "+(son.getMonth()+1)+" - "+son.getFullYear(); var hora=son.getHours()+":"+son.getMinutes()+":"+son.getSeconds(); var escribe='Hoy es '+fecha+' y son las '+hora+' horas'; var situa=document.getElementById('capa0'); situa.innerHTML=escribe; reloj=setTimeout("actualiza()",frecuencia); } </script> </head> <body onLoad="actualiza()";> <div id="capa0"> </div> </body> </html>
ejemplo3.html

Lenguajes del lado del servidor


Un lenguaje es del lado del servidor cuando la ejecucin de sus scripts se efecta, por instancia de este el servidor, antes de dar respuesta a la peticin, de manera que el cliente no recibe el documento original sino el resultante de esa interpretacin previa. Cuando se usan estos tipos de lenguaje el cliente recibe un documento en el que cada script contenido en el original habr sido sustituido por los resultados de su ejecucin. Esto es algo a tener muy en cuenta, porque, en este caso, los usuarios no tendrn la posibilidad de visualizar el cdigo fuente, mientras que cuando se trata de lenguajes del lado del cliente siempre es posible visualizar los scripts, bien sea de forma directa mirando el cdigo fuente de la pgina recibida o leyendo el contenido de ficheros externos vinculados a ella que son bastante fciles de encontrar en la cach del navegador. La utilizacin de este tipo de scripts requiere que el intrprete del lenguaje sea accesible est del lado desde el propio servidor. Entre los lenguajes del lado del servidor los ms populares son: PHP, ASP, PERL y JSP. Cada uno de ellos tiene sus propias peculiaridades. No abundaremos en ellas. Nosotros trataremos aqu sobre PHP.

Las posibles dudas del servidor


Dado que en unos casos el servidor debe entregar el documento original pginas estticas o pginas dinmicas en las que se usan lenguajes del lado del cliente mientras que en otros casos pginas dinmicas usando lenguajes del lado del servidor tiene que devolver el resultado de la ejecucin de los scripts, es razonable que te preguntes: cmo sabe el servidor lo que debe hacer en cada caso? La respuesta es simple. Eso hay que decrselo. Y se le dice de una forma bastante simple. Se indica al poner la extensin al documento. Si en la peticin se alude a un documento con extensin .htm o .html el servidor entender que esa pgina no requiere la intervencin previa de ningn intrprete de su lado y entregar la pgina tal cual. Si en esa peticin se aludiera a una extensin distinta .php, por ejemplo el servidor entendera que antes de servir la pgina debe leerla y requerir al intrprete de PHP que ejecute los scripts desarrollados en ese lenguaje (en caso de que los contuviera) y devolvera al cliente el documento que resultara de las eventuales ejecuciones de tales scripts. Aqu tienes el esquema de un ejemplo de convivencia en un mismo documento de varios scripts y varios tipos de lenguaje.

Aqu ya es preciso que, adems de un servidor capaz de soportar el protocolo HTTP, est instalado del lado del servidor un intrprete PHP, un servidor de bases de datos MySQL y que, adems, estn configurados de modo que puedan interactuar entre ellos. El lenguaje PHP dispone de funciones que le permiten acceder a muy diversos tipos de servidores de bases de datos pudiendo: crear, consultar, borrar y modificar tanto bases de datos como tablas y registros de las mismas. Nosotros vamos a utilizar MySQL, unos de los gestores ms potentes y populares que existen en este momento.

Requisitos para el uso del Lenguaje PHP


De acuerdo a lo comentado en los prrafos anteriores el uso del lenguaje PHP requiere tener instalado y configurado: Un software de servidor web configurado para interactuar con el intrprete de PHP que soporte el protocolo HTTP y que en nuestro caso ser el denominado servidor Apache. El intrprete de PHP. Un software de servidor de bases de datos capaz de ser gestionado mediante funciones propias de PHP. Podemos utilizar el servidor de bases de datos MySQL o su fork MariaDB (me gust eso del fork!) y tambin podrs encontrar referencias al uso deSQLite que en muchos casos puede resultar una alternativa ms ligera y accesible.

PHP y HTML Pginas PHP


Las pginas PHP pueden ser pginas web normales a las que nicamente se les cambia la extensin tradicional (.htm .html) , por la extensin .php. Observemos este cdigo fuente. Como vers, se trata de una pgina web muy simple que no contiene ningn script PHP.

<html>

<head> <title>Aprendiendo PHP</title></head> <body> Esta es una pgina supersimple </body> </html>
Hemos guardado esa pgina con el nombre ejemplo6.html y luego la hemos vuelto a guardar sin modificar nada en sus contenidos como ejemplo6.php. Observa que al visualizarlas no hay diferencia alguna entre ellas.
Ver ejemplo6.html Ver ejemplo6.php

Un poco de sintaxis
En una pgina cuyo nombre tenga por extensin .php se pueden insertar instrucciones escritas en lenguaje PHP anteponiendo <?php a la primera instruccin y escribiendo ?> despus de la ltima. A cada uno de estos bloques de instrucciones le llamaremos un script. No existe lmite en cuanto al nmero de scripts distintos que pueden insertarse dentro de una pgina. La primera instruccin PHP que conoceremos ser esta: echo "un texto...";. La instruccin echo seguida de un texto entrecomillado har que el PHP escriba en la pgina web resultante lo contenido en esa cadena de texto. Al final de cada instruccin debemos insertar siempre un punto y coma (;). Este signo (;) indicar a PHP que lo que viene a continuacin es una nueva instruccin. Para facilitar la depuracin de los scripts no suelen escribirse dos instrucciones en una misma lnea. print "un texto ...";

La instruccin print tiene una funcin similar no es exactamente la misma a la descrita para echo. Ms adelante veremos algunas de sus diferencias. print ("un texto...");

Esta es otra manera la ms habitual de utilizar print. Ahora encerramos entre parntesis la cadena que pretendemos que aparezca impresa en la pgina web. El hecho de que utilicemos parntesis no evita la obligacin de encerrar entre comillas el texto (texto) que deseamos imprimir . Comillas dentro de comillas

Existen dos tipos de comillas: dobles " (SHIFT+2) y sencillas ' (tecla ? en minsculas). Cuando es preciso anidar comillasdeben utilizarse tipos distintos para las exteriores y para las interiores. Para que una instruccin echo o print interprete unas comillas como texto y no como un delimitador de la cadena es necesarioanteponerles un signo de barra invertida(\). En argot suele decirse escaparlas. En ningn caso ni con echo ni con print est permitido sustituir las comillas exteriores (las que encierran la cadena) por \". Esta sintaxis solo es vlida para indicar a PHP que debe interpretar las comillas como un carcter ms. En la pgina siguiente veremos las diferentes opciones de las lneas de comentarios. Al realizar el ejercicio que te proponemos no es necesario que pongas los comentarios del ejemplo.

Los primeros script PHP


Editemos la pgina anterior (ejemplo6.php) y aadmosle nuestra primera etiqueta PHP guardndola como ejemplo7.php. Este sera el cdigo fuente:

<html> <head> <title>Aprendiendo PHP</title></head> <body> Esta es una pgina supersimple <?php echo "Aparecer esta linea?"; ?> </body> </html>
ejemplo7.php

Veamos ahora un ejemplo con las diferentes opciones de uso de las comillas

<html> <head> <title>Aprendiendo PHP</title></head> <body> <?php /* Las instrucciones PHP son las que aparecen en rojo. Las etiquetas en azul intenso son el cdigo HTML. Todo lo que aparece en este color son lneas de comentario de las que hablaremos ms adelante Cuando rescribas estos primeros scripts bastar que incluyas las instrucciones escritas en rojo */ /* ponemos <br> al final del texto para que cuando se ejecute cada una de las instrucciones echo se escriba -adems del texto- un salto de linea HTML. De este modo, el resultado de cada ECHO aparecer en una lnea diferente */ # aqu utilizamos solo unas comillas echo "Este texto solo lleva las comillas de la instruccin<br>"; # aqu anidaremos comillas de distinto tipo echo "La palabra 'comillas' aparecer entrecomillada<br>"; # esta es otra posibilidad invirtiendo el orden de las comillas echo 'La palabra "comillas" aparecer entrecomillada<br>'; # una tercera posibilidad en la que utilizamos un mismo # tipo de comillas. Para diferenciar unas de otras anteponemos # la barra invertida, pero esta opcin no podramos utilizarla # al revs. # No podramos poner \" en las comillas exteriores. echo "La palabra \"comillas\" usando la barra invertida<br>"; ?> </body> </html>
Ver ejemplo8.php

Lneas de comentario Por qu usar lneas de comentario?


A primera vista pueden parecer intiles. Para qu recargar las pginas con contenidos que no se van a ver ni ejecutar?. Las lneas de comentario sirven para poder recordar en un futuro qu es lo que hemos hecho al escribir un script y por qu razn lo hemos hecho as.

A medida que vayamos avanzando vers que en muchos casos tendremos que aplicar estrategias individuales para resolver cada problema concreto. Cuando necesites hacer una correccin o una modificacin al cabo de un tiempo vers que confiar en la memoria no es una buena opcin. Es mucho mejor utilizar una lnea de comentario que confiar en la memoria. Palabra!

Comentarios
Para insertar comentarios en los scripts de PHP podemos optar entre varios mtodos y varias posibilidades: Una sola linea

Basta colocar los smbolos // al comienzo de la lnea o detrs del punto y coma que seala el final de una instruccin. Tambin se puede usar el smbolo # en cualquiera de las dos posiciones. Varias lneas

Si un comentario va a ocupar ms de una lnea podremos escribir /* al comienzo de la primera de ellas y */ al final de la ltima. Las lneas intermedias no requieren de ningn tipo de marca. Los comentarios para los que usemos la forma /* ... */ no pueden anidarse. Si, por error, lo hiciramos PHP nos dar un mensaje de error.

Ensayando lneas de comentario


En este ejemplo hemos incluido marcados en rojo algunos ejemplos de insercin de lneas de comentario.

<html> <head> <title>Ejemplo 9</title></head> <body> <?php // Este comentario no se ver en la pgina echo "Esto se leer <BR> "; // Esto no se leer /* Este es un comentario de mltiples lneas y no se acabar hasta que no cerremos as.... */ echo "Este es el segundo comentario que se leer<BR>"; # Este es un comentario tipo shell que tampoco se leer # Este, tampoco echo ("Aqu el tercer texto visible"); #comentario invisible /* Cuidado con anidar /* comentarios multilinea con estos*/ al PHP no le gustan */ ?> </body> </html>
Ver ejemplo9.php Ver ejemplo10.php

Ejecutemos los dos ejemplos. En el caso del ejemplo9 hemos mantenido el cdigo exactamente como se muestra aqu arriba. Como consecuencia de haber anidado comentarios nos dar un error al ejecutarlo. Esto es una muestra de la importancia que tiene cuidar estrictamente ese aspecto.

En el ejemplo10 hemos quitado el /* que va delante de comentarios y el */ que va despus de multilnea con estos (marcado en magenta en el cdigo fuente). Ya no hay comentarios anidados y ya funciona correctamente.

Cuidado! Si tu sistema operativo es Ubuntu es muy probable que en vez de los mensajes de error comentados en los ejemplos anteriores solo visualices una pgina en blanco. Ello es debido a la configuracin por defecto de la directiva display_errors de php.ini. En este enlace (http://www.rinconastur.com/php/errores.php) tienes informacin relativa a la configuracin de las directivas de error.

Constantes Definir constantes


Una constante es un valor un nmero o una cadena que no va a ser modificado a lo largo del proceso de ejecucin de los scriptsque contiene un documento. Para mayor comodidad, a cada uno de esos valores se le asigna un nombre, de modo que cuando vaya a ser utilizado baste con invocar ese nombre. Cuando ponemos nombre a una constante se dice que definimos esa constante. En PHP las constantes se definen mediante la siguiente instruccin: define("nombre","valor");

dnde nombre es una cadena que contiene la palabra que pretendemos asignar como tal nombre y valor el contenido que pretendemos asignar a esa constante. El valor debe escribirse entre comillas, salvo que se trate de una constantes numrica que no las requiere. Los valores asignados a las constantes se mantienen en todo el documento, incluso cuando son invocadas desde una funcin. Si se realizan operaciones aritmticas con constantes tipo cadena, y su valor comienza por una letra, PHP les asigna valor cero. Si una cadena empieza por uno o varios caracteres numricos, al tratar de operarla aritmticamente PHP considerar nicamente el valor de los dgitos anteriores a la primera letra o carcter no numrico. El punto entre caracteres numricos es considerado como separador de parte decimal. Tal como puedes ver en el cdigo fuente del ejemplo, es posible definir constantes a las que se asigne como valor el resultado de una operacin aritmtica.

Ampliando echo y print


Mediante una sola instruccin echo pueden presentarse de forma simultnea (en la ventana del navegador del cliente) varias cadenas de caracteres y/o constantes y variables. Basta con ponerlas una a continuacin de otra utilizando una coma como separador. La forma anterior no es la nica ni la ms habitual de enlazar elementos mediante la instruccin echo. Si en vez de utilizar la una coma usramos un un punto (el concatenador de cadenas) conseguiramos el mismo resultado. Cuando enlacemos elementos distintos cadenas, constantes y/o nmeros hemos de tener muy en cuenta lo siguiente: Cada una de las sucesivas cadenas debe ir encerrada entre sus propias comillas. Los nombres de constantes nunca van entre comillas.

Las instrucciones print tambin permiten concatenar cadenas en una misma instruccin. En este caso solo es posible usar un puntocomo elemento de unin. Si pusiramos comas como podemos hacer con echo PHP nos dara un error.

Un ejemplo con constantes


<html><head><title>Constantes</title></head> <body> <?php /* Definiremos la constante EurPta y le asignaremos el valor 166.386 */ define("EurPta",166.386); /* Definiremos la constante PtaEur asignndole el valor 1/166.386 En este caso el valor de la constante es el resultado de la operacin aritmtica dividir 1 entre 166.386*/ define("PtaEur",1/166.386); /* Definimos la constante Cadenas y le asignamos el valor: 12Esta constante es una cadena*/ define("Cadena","12Esta constante es una cadena"); /* Definimos la constante Cadena2 y le asignamos el valor: 12.54Constante con punto decimal*/ define("Cadena2","12.54Constante con punto decimal"); /* Comprobemos los valores. Observa la nueva forma en la que utilizamos echo Lo hacemos enlazando varias cadenas separadas con punto y/o coma, segn se trate de echo o de print */ echo "Valor de la constante EurPta: ", EurPta, "<BR>"; echo "Valor de la constante PtaEur: ". PtaEur . "<BR>"; print "Valor de la constante Cadena: " . Cadena . "<BR>"; print "Valor de la constante Cadena x EurPta: " . Cadena*EurPta ."<br>"; print "Valor de la constante Cadena2 x EurPta: " . Cadena2*EurPta ."<br>"; echo "Con echo los nmeros no necesitan ir entre comillas: " ,3,"<br>"; print "En el caso de print si son necesarias: " . "7" . "<br>"; print ("incluso entre parntesis necesitan las comillas: "."45"."<br>"); print "Solo hay una excepcin en el caso de print. "; print "Si los nmeros van en un print independiente no necesitan comillas "; print 23; # Pondremos la etiqueta de cierre del script y escribiremos # una lnea de cdigo HTML ?> <br>Ahora veremos los mismos resultados usando la function prueba<br><br> <?php # Estamos dentro de un nuevo script abierto por el <? anterior

/* Aunque an no la hemos estudiado, escribiremos una funcin a la que (tenemos que ponerle siempre un nombre) vamos a llamar prueba() Lo sealado en rojo es la forma de indicar el comienzo y el final de la funcion Lo marcado en azul son las instrucciones que deben ejecutarse cuando la funcin prueba() sea invocada */ function prueba(){ echo "Valor de la constante EurPta: ". EurPta . "<BR>";

print "Valor de la constante PtaEur: ". PtaEur. "<BR>"; echo "Valor de la constante Cadena: ", Cadena , "<BR>"; print ("Valor de la constante Cadena x EurPta: " . Cadena*EurPta . "<br>"); print ("Valor de la constante Cadena2 x EurPta: " . Cadena2*EurPta . "<br>"); } # Las funciones solo se ejecutan cuando son invocadas /* La funcin anterior no se ejecutar hasta que escribamos una lnea como esta de abajo en la que ponemos nicamente el nombre de la funcin: prueba() */ ?> <?php prueba(); ?> </body> </html>
Ver ejemplo11.php

Cuidado! Presta mucha atencin a la sintaxis. Olvidar los ; o no poner unas comillas suelen ser la causa de muchos mensajes de error.

Variables Qu es una variable?


Podramos decir que una variable es el espacio de la memoria RAM del ordenador que se reserva a lo largo del tiempo de ejecucin de un script para almacenar un determinado tipo de datos cuyos valores son susceptibles de ser modificados por medio de las instrucciones contenidas en el propio programa. En PHP todos los nombres de variable tienen que empezar por el smbolo $.y han de llevar una letra inmediatamente despus del smbolo $ ($pepe1 es un nombre vlido, pero $1pepe no lo es). Para PHP las letras maysculas y las minsculas son distintas. La variable $pepe es distinta de $Pepe.

Definicin y tipos de variables


A diferencia de otros lenguajes de programacin, PHP no requiere una definicin previa de las variables. Se pueden definen en el momento en que son necesarias y para ello basta que se les asigne un valor por medio de una expresin como esta: $variable=valor;

donde valor puede ser una cadena (texto, texto y nmeros, o nmeros que no requieren ser operados matemticamente) o slo unnmero. En el primero de los casos habra que escribirlo entre comillas. En PHP tampoco es necesario definir el tipo de variable, por lo tanto, una misma variable puede contener una cadena de caracteresen un momento del proceso y, posteriormente, un valor numrico susceptible de ser operado matemticamente.

Cuidado! En algunas configuraciones de PHP el uso de variables no definidas previamente puede dar lugar a mensajes de error como el que puedes observar si ejecutas el ejemplo12.php desde PHP 5.3.6 utilizando la configuracin explicada en

pginas anteriores. El mensaje se debe a la forma en la que est configuradas la directiva relativa a los mensajes de error cuya explicacin puedes ver en este enlace. Ese mensaje de error puede evitarse de la forma que hemos hecho en el ejemplo14.php o modificando la directiva error_reporting o display_errors tal como se comenta aqu

mbito de las variables


Los valores de una variable definida en cualquier parte de un script siempre que no sea dentro de una funcin pueden ser utilizados desde cualquier otra parte de ese script, excepto desde dentro de las funciones que contuviera el propio script o desde las que pudieran estar contenidas en un fichero externo. Si una variable es definida dentro de una funcin slo podr ser utilizada dentro esa funcin. Si en una funcin aludimos a una variable externa a ella, PHP considerar esa llamada como si la variable tuviera valor cero (en caso de ser tratada como nmero) o una cadena vaca ("" es una cadena vaca). Igual ocurrira si desde fuera de una funcin hiciramos alusin a una variable definida en ella. Si definimos dos variables con el mismo nombre, una dentro de una funcin y otra fuera, PHP las considerar distintas. La funcin utilizar cuando sea ejecutada sus propios valores sin que sus resultados modifiquen la variable externa.

Variables globales
Lo comentado anteriormente, admite algunas excepciones. Las funciones pueden utilizar valores de variables externas a ellas pero ello requiere incluir dentro de la propia funcin la siguiente instruccin: global nombre de la variable;

Por ejemplo: global $a1; permitira utilizar el valor preexistente de esa variable dentro de una funcin. Las eventuales modificaciones que pudiera producirle la funcin mantendran su nuevo valor despus de finalizar la ejecucin de la funcin. En una instruccin global pueden definirse como tales, de forma simultnea, varias variables. Basta con escribir los nombres de cada una de ellas separados por comas. Por ejemplo: global $a1, $a2, $a3;

Variables superglobales
A partir de la versin 4.1.0 de PHP se ha creado un nuevo tipo de variables capaces de comportarse como globales sin necesidad de que se definan como tales. Estas variables que no pueden ser creadas por usuario, recogen de forma automtica informacin muy especficay tienen nombres preasignados que no pueden modificarse. Las estudiaremos un poco ms adelante. Por ahora, slo citar los nombres de algunas de ellas: $_SERVER, $_POST, $_GET, $_ENVo $_SESSION son los de algunas de las ms importantes.

Practicando con variables y sus mbitos


El cdigo fuente que ves aqu debajo corresponde al ejemplo12.php. Si pulsas en el enlace que hay debajo y ejecutas el script vers que aparece un mensaje de error que dice: Notice: Undefined variable: pepe ... que parece contradictorio con lo afirmado ms arriba respecto a que PHP no requiere una definicin previa de variables. Esa afirmacin es cierta. Lo que ocurre es que PHP no est dando un mensaje de error propiamente dicho (NOTICE es una simple advertencia con un significado distinto a ERROR ) sino que advierte de que no se ha hecho algo habitual en una gran cantidad de lenguajes. Hay dos formas de evitar ese mensaje. La primera de ellas la comentamos en el propio cdigo fuente sera definir las variables antes de usarlas (siguiendo la metodologa ms generalizada de programacin). La segunda de las opciones sera modificar el fichero php.ini cambiando el valor actual: error_reporting = E_ALL | E_STRICT por error_reporting = E_ALL &

~E_NOTICE. De esta forma, (al anteponer ~aE_NOTICE) estaremos indicando a PHP , tal como explicamos aqu, que desactive este tipo de mensajes de advertencia.

<html> <head> </head> <body> <?php /* En ejemplo12.php la linea siguiente a este comentario($pepe="" ) estar marcada con lneas de comentario mientras que en ejemplo13.php y ejemplo14.php aparecer tal como la ves aqu */ $pepe=""; # Definimos las variables $Pepe y $Pepa (ojo con maysculas y minsculas) $Pepe="Me llamo Pepe y soy serio y formal"; $Pepa="Me llamo Pepa y tambin soy seria y formal"; ?> <!-- esto es HTML, hemos cerrado el script --> <center><b>Vamos a ver el contenido de las variables</b></center> <!-un nuevo script PHP -->

<?php echo "<br> El valor de la variable $pepe es: ",$pepe; echo "<br> No ha puesto nada porque $pepe esta vaca"; echo "<br> El valor de la variable Pepe es: ",$Pepe; ?> <center><b><br>Invocando la variable desde una funcin</b></center> <?php /* Escribiremos una function llamada vervariable Observa la sintaxis. La palabra function delante y el () al final seguidos de la llave. Hasta que no cerremos la llave todas las lneas sern consideradas parte de la funcin */ function vervariable(){ // $Pepe=""; /* si no inicializamos la variable $Pepe nos puede aparecer el mensaje de error que comentamos al margen y que veremos al ejecutar este script tanto desde el enlace ejemplo12.php como desde el ejemplo13.php En el caso del ejemplo14.php, donde ya no aparece el error lo nico que hemos hecho ha sido precisamente inicializar la variable $Pepe asignndole un valor nulo tal como puedes ver en la lnea anterior (marcado en rojo) y comentada con // En el ejemplo14.php hemos descomentar esta lnea */ echo "<br> Si invoco la variable Pepe desde una funcin"; echo "<br>me aparecer en blanco"; echo "<br>El valor de la variable Pepe es: ",$Pepe; } /* esta llave de arriba seala el final de la funcin. Los contenidos que hay en adelante ya no pertenecen a ella */ /* Haremos una llamada a la funcion vervariable. Las funciones no se ejecutan hasta que no se les ordena y se hace de esta forma que ves aqu debajo: nombre de la funcion seguido de los famosos parntesis */

vervariable(); ?> <!-- mas HTML puro --> <center><b><br>Ver la variable desde la funcin poniendo <i>global</i></b></center> <?php # una nueva funcion function ahorasi(){ # aqui definiremos a $Pepe como global # la funcin leer su valor externo global $Pepe; echo "<br><br> Hemos asignado mbito global a la variable"; echo "<br>ahora Pepe aparecer"; echo "<br>El valor de la variable Pepe es: ", $Pepe; } # hemos cerrado ya la funcion con la llave. # Tendremos que invocarla para que se ejecute ahora ahorasi(); ?> <center><b><br>Un solo nombre y dos <i>variables distintas</i></b><br> Dentro de la funcin el valor de la variable es <br></center> <?php function cambiaPepa(){ $Pepa="Ahora voy a llamarme Luisa por un ratito"; echo "<br>",$Pepa; } cambiaPepa(); ?> <center>... pero despus de salir de la funcin vuelvo al valor original...</center> <?php echo "<br>",$Pepa; ?> </body> </html>
Ver ejemplo12.php Ver ejemplo13.php Ver ejemplo14.php

Constantes predefinidas Constantes predefinidas


PHP dispone de algunas constantes predefinidas que no requieren la instruccin: define("Nombre","Valor") ya que utilizan palabras reservadas y se asignan valor de forma automtica. Algunas de ellas son estas: __FILE__

Recoge el nombre del fichero que se est ejecutando y la ruta completa de su ubicacin en el servidor. Su nombre lleva dos guiones bajos ( __ ) delante de FILE y otros dos detrs. __LINE__

Recoge el nmero de la lnea actual (incluidas las lneas en blanco) del fichero PHP cuyos scripts est interpretando. Puede resultar muy til para depurar programas. PHP_OS

Recoge informacin sobre el sistema operativo que utiliza el servidor en el que se est interpretando el fichero. PHP_VERSION

Recoge la versin de PHP que est siendo utilizada por el servidor.

Cuidado! Por si existieran dudas por problemas de visualizacin tanto FILE como LINE tienen que llevar dos guiones bajosdelante y otras dos detrs.

Un ejemplo con constantes predefinidas


<html> <head> </head> <body> <?php # La constante del sistema __FILE__ nos devolver echo "La ruta completa de este fichero es: "; echo __FILE__; # # # # La constante del sistema __LINE__ nos devolver el nmero de lnea que se est interpretando tambin cuenta las lneas en blanco cuenta las lneas y vers que devuelve ... 16

echo "<br>Esta es la lnea: ",__LINE__, " del fichero"; echo "<br>Estamos utilizando la versin: ",PHP_VERSION, " de PHP"; echo "<br>El PHP se est ejecutando desde el sistema operativo: ",PHP_OS; ?> </body> </html>
Ver ejemplo15.php

Variables predefinidas
Las tablas de valores
En las tablas que hay al final de esta pgina podrs ver los valores actuales clasificados por tipos de algunas de las variables predefinidas de PHP. Esta informacin (variables y valores) est siendo extraida de la configuracin de tu servidor y de este documento y se trata de variables de tipo superglobal tal como lo definamos en esta pgina. Probablemente te extraar justificadamente la longitud y la estructura un tanto rara de estos nombres de variables. Cuando tratemos el tema de los arrays asociativos veremos que esa es la sintaxis habitual de ese tipo de variables. Las nombres de las variables de cada uno de los tipos, slo se diferencian en lo contenido entre los corchetes porque se trata dedistintos elementos del mismo array asociativo y tal como veremos esa es la sintaxis tpica de los array. No vamos a agobiarte con una enumeracin de variables y contenidos, pero a poco que observes las tablas de valores te dars cuenta de que es muy abundante y muy importante la informacin que recogen. Si analizas las variables de servidor te dars cuenta de que aparece un montn de informacin relativa a su configuracin: nombre, rutas, nombres de pginas, IP del servidor, etctera. Con los dems tipos ocurre algo similar.

Los distintos tipos


Veamos los diferentes tipos de variables predefinidas que existen en PHP. Por ahora, no te preocupes demasiado sobre la forma de utilizarlas. Las incluimos aqu como una simple enumeracin y con una breve descripcin de su utilidad. En temas posteriores haremos referencia a ellas. Por el momento nos bastar con conocer su existencia. Estamos viendo los valores de las variables de de entorno (ENV) y las de servidor (SERVER), pero, adems de ellas, existen algunas otras cuyos nombres y utilidades vamos a comentarte.

Variables de sesin
Las identificaremos por el nombre $_SESSION. Este tipo de variables las utilizaremos cuando hagamos mencin al uso de sesiones. La utilizacin de sesiones ya abundaremos en ello es una forma de recoger, de forma temporal en un documento del mismo carcter, informacin especfica generada a travs de los accesos de cada uno de los usuarios. Por ejemplo, cuando accedes a una cuenta de correo web y escribes tu clave y contrasea se crea un documento temporal en el servidor de correo con un nmero nico y exclusivo para ese acceso identificador de sesin que te permite acceder a diferentes apartados sin necesidad de que reescribas, en cada una de las pginas, esos mismos valores. Habrs comprobado tambin, ms de una vez, su carcter efmero cuando al actualizar una pgina te ha aparecido ese mensaje tpico que dice la sesion ha caducado.

Variables de los mtodos GET y POST


Las identificaremos por los nombres $_GET y $_POST Este tipo de variables que utilizaremos con frecuencia recogen la informacin que se enva desde el cliente para ser utilizada por el servidor. Recuerda el carcter dinmico de PHP y que ese dinamismo (interaccin cliente servidor) requiere que el servidor guarde y/o interprete los datos remitidos por el cliente. La existencia de los dos tipos se justifica porque tambin existen dos tipos de mtodos(maneras) de enviar datos desde el cliente hasta el servidor. Cuando el mtodo de envo es el llamado GET los datos se recogen en variables de este tipo, y, por el contrario, si ese mtodo envo fuera POST se recogeran en aquellas.

Variables de transferencia de ficheros


Las identificaremos por el nombre $_FILES. Cuando se trata de la transferencia de un fichero desde el cliente hasta el servidor subir un fichero es necesario utilizar un procedimiento de envo distinto de los comentados en el prrafo anterior. Ser en este caso cuando se utilicen variables de este tipo.

El tipo GLOBALS

A diferencia de las anteriores, las variables de este tipo, $GLOBALS,utilizan una sintaxis algo distinta ya no llevan el guin bajo detrs de $. Su finalidad es recoger en una tabla los nombres de todas la variables establecidas como globales en cada momento as como sus valores. Si observas la tabla que tienes al final de esta pgina quiz te sorprenda leer nombre o pgina. De donde han salido esos valores?. Bueno... en esta pgina utilizamos scripts PHP y esos son los nombres de unas variables que hemos incluido en ellos. Conocida la existencia de los diferentes tipos de variables predefinidas y vista esta tabla a modo de ejemplo de su utilidad no ser preciso que profundicemos ms en el asunto. Lo trataremos en el momento en el que tengamos que hacer uso de cada una de ellas.

Variables de servidor
$_SERVER['UNIQUE_ID']

il4An0g0jIEAAHqC@fQAAAAO
$_SERVER['HTTP_HOST']

www.rinconastur.com
$_SERVER['HTTP_CONNECTION']

keep-alive
$_SERVER['HTTP_USER_AGENT']

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5


$_SERVER['HTTP_ACCEPT']

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q= 0.8
$_SERVER['HTTP_REFERER']

http://www.rinconastur.com/php/php29.php
$_SERVER['HTTP_ACCEPT_ENCODING']

gzip,deflate,sdch
$_SERVER['HTTP_ACCEPT_LANGUAGE']

es-ES,es;q=0.8
$_SERVER['HTTP_ACCEPT_CHARSET']

ISO-8859-1,utf-8;q=0.7,*;q=0.3
$_SERVER['HTTP_COOKIE']

PHPSESSID=ed3f35bf913ecbae9d18c30daff4f6e8
$_SERVER['PATH']

/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$_SERVER['SERVER_SIGNATURE']

$_SERVER['SERVER_SOFTWARE']

Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8e-fips-rhel 5 mod_bwlimited/1.4 PHP/5.2.11


$_SERVER['SERVER_NAME']

www.rinconastur.com
$_SERVER['SERVER_ADDR']

72.52.140.129
$_SERVER['SERVER_PORT']

80
$_SERVER['REMOTE_ADDR']

190.82.98.194
$_SERVER['DOCUMENT_ROOT']

/home/rinconas/public_html
$_SERVER['SERVER_ADMIN']

webmaster@rinconastur.net

$_SERVER['SCRIPT_FILENAME']

/home/rinconas/public_html/php/php30.php
$_SERVER['REMOTE_PORT']

33367
$_SERVER['GATEWAY_INTERFACE']

CGI/1.1
$_SERVER['SERVER_PROTOCOL']

HTTP/1.1
$_SERVER['REQUEST_METHOD']

GET
$_SERVER['QUERY_STRING']

$_SERVER['REQUEST_URI']

/php/php30.php
$_SERVER['SCRIPT_NAME']

/php/php30.php
$_SERVER['PHP_SELF']

/php/php30.php
$_SERVER['REQUEST_TIME']

1338997030
$_SERVER['argv']

$_SERVER['argc']

Variables GLOBALES
$GLOBALS['GLOBALS']['GLOBALS']

Array
$GLOBALS['GLOBALS']['_ENV']

Array
$GLOBALS['GLOBALS']['HTTP_ENV_VARS']

Array
$GLOBALS['GLOBALS']['_POST']

Array
$GLOBALS['GLOBALS']['HTTP_POST_VARS']

Array
$GLOBALS['GLOBALS']['_GET']

Array
$GLOBALS['GLOBALS']['HTTP_GET_VARS']

Array
$GLOBALS['GLOBALS']['_COOKIE']

Array
$GLOBALS['GLOBALS']['HTTP_COOKIE_VARS']

Array
$GLOBALS['GLOBALS']['_SERVER']

Array
$GLOBALS['GLOBALS']['HTTP_SERVER_VARS']

Array

$GLOBALS['GLOBALS']['_FILES']

Array
$GLOBALS['GLOBALS']['HTTP_POST_FILES']

Array
$GLOBALS['GLOBALS']['_REQUEST']

Array
$GLOBALS['GLOBALS']['xyz_DOCUMENT_ROOT']

C:/ServidoresLocales/Apache/htdocs
$GLOBALS['GLOBALS']['mi_xyz']

$GLOBALS['GLOBALS']['xyz_SERVER_ROOT']

C:/ServidoresLocales/Apache/
$GLOBALS['GLOBALS']['xyz_INSTALL']

C:/ServidoresLocales/
$GLOBALS['GLOBALS']['xyz_DIR_INSTALL']

ServidoresLocales
$GLOBALS['GLOBALS']['ver']

ver.php?URL=
$GLOBALS['GLOBALS']['ver_extension']

.php
$GLOBALS['GLOBALS']['extension']

.php
$GLOBALS['GLOBALS']['prefijo']

$GLOBALS['GLOBALS']['incluye']

general.inc.php
$GLOBALS['GLOBALS']['prefx']

$GLOBALS['GLOBALS']['prefx1']

$GLOBALS['GLOBALS']['prefx0']

$GLOBALS['GLOBALS']['opcion']

I
$GLOBALS['GLOBALS']['anterior']

php29.php
$GLOBALS['GLOBALS']['siguiente']

php31.php
$GLOBALS['GLOBALS']['clave']

Array
$GLOBALS['GLOBALS']['nombre']

argc
$GLOBALS['GLOBALS']['nombre1']

GLOBALS
$GLOBALS['GLOBALS']['valor']

GLOBALS
$GLOBALS['GLOBALS']['nombre2']

valor
$GLOBALS['_ENV']['TERM']

vt100

$GLOBALS['_ENV']['SSH_CLIENT']

80.35.161.51 52129 22
$GLOBALS['_ENV']['CPANEL_IS_CRON']

0
$GLOBALS['_ENV']['LD_LIBRARY_PATH']

/usr/local/apache/lib:
$GLOBALS['_ENV']['PATH']

/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['_ENV']['PWD']

/usr/local/cpanel/whostmgr/docroot
$GLOBALS['_ENV']['SHLVL']

1
$GLOBALS['_ENV']['RESTARTSRV']

1
$GLOBALS['_ENV']['_']

/usr/local/apache/bin/httpd
$GLOBALS['HTTP_ENV_VARS']['TERM']

vt100
$GLOBALS['HTTP_ENV_VARS']['SSH_CLIENT']

80.35.161.51 52129 22
$GLOBALS['HTTP_ENV_VARS']['CPANEL_IS_CRON']

0
$GLOBALS['HTTP_ENV_VARS']['LD_LIBRARY_PATH']

/usr/local/apache/lib:
$GLOBALS['HTTP_ENV_VARS']['PATH']

/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['HTTP_ENV_VARS']['PWD']

/usr/local/cpanel/whostmgr/docroot
$GLOBALS['HTTP_ENV_VARS']['SHLVL']

1
$GLOBALS['HTTP_ENV_VARS']['RESTARTSRV']

1
$GLOBALS['HTTP_ENV_VARS']['_']

/usr/local/apache/bin/httpd
$GLOBALS['_COOKIE']['PHPSESSID']

ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['HTTP_COOKIE_VARS']['PHPSESSID']

ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['_SERVER']['UNIQUE_ID']

il4An0g0jIEAAHqC@fQAAAAO
$GLOBALS['_SERVER']['HTTP_HOST']

www.rinconastur.com
$GLOBALS['_SERVER']['HTTP_CONNECTION']

keep-alive
$GLOBALS['_SERVER']['HTTP_USER_AGENT']

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5


$GLOBALS['_SERVER']['HTTP_ACCEPT']

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
$GLOBALS['_SERVER']['HTTP_REFERER']

http://www.rinconastur.com/php/php29.php

$GLOBALS['_SERVER']['HTTP_ACCEPT_ENCODING']

gzip,deflate,sdch
$GLOBALS['_SERVER']['HTTP_ACCEPT_LANGUAGE']

es-ES,es;q=0.8
$GLOBALS['_SERVER']['HTTP_ACCEPT_CHARSET']

ISO-8859-1,utf-8;q=0.7,*;q=0.3
$GLOBALS['_SERVER']['HTTP_COOKIE']

PHPSESSID=ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['_SERVER']['PATH']

/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['_SERVER']['SERVER_SIGNATURE']

$GLOBALS['_SERVER']['SERVER_SOFTWARE']

Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4 PHP/5.2.11


$GLOBALS['_SERVER']['SERVER_NAME']

www.rinconastur.com
$GLOBALS['_SERVER']['SERVER_ADDR']

72.52.140.129
$GLOBALS['_SERVER']['SERVER_PORT']

80
$GLOBALS['_SERVER']['REMOTE_ADDR']

190.82.98.194
$GLOBALS['_SERVER']['DOCUMENT_ROOT']

/home/rinconas/public_html
$GLOBALS['_SERVER']['SERVER_ADMIN']

webmaster@rinconastur.net
$GLOBALS['_SERVER']['SCRIPT_FILENAME']

/home/rinconas/public_html/php/php30.php
$GLOBALS['_SERVER']['REMOTE_PORT']

33367
$GLOBALS['_SERVER']['GATEWAY_INTERFACE']

CGI/1.1
$GLOBALS['_SERVER']['SERVER_PROTOCOL']

HTTP/1.1
$GLOBALS['_SERVER']['REQUEST_METHOD']

GET
$GLOBALS['_SERVER']['QUERY_STRING']

$GLOBALS['_SERVER']['REQUEST_URI']

/php/php30.php
$GLOBALS['_SERVER']['SCRIPT_NAME']

/php/php30.php
$GLOBALS['_SERVER']['PHP_SELF']

/php/php30.php
$GLOBALS['_SERVER']['REQUEST_TIME']

1338997030
$GLOBALS['_SERVER']['argv']

Array
$GLOBALS['_SERVER']['argc']

$GLOBALS['HTTP_SERVER_VARS']['UNIQUE_ID']

il4An0g0jIEAAHqC@fQAAAAO
$GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST']

www.rinconastur.com
$GLOBALS['HTTP_SERVER_VARS']['HTTP_CONNECTION']

keep-alive
$GLOBALS['HTTP_SERVER_VARS']['HTTP_USER_AGENT']

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5


$GLOBALS['HTTP_SERVER_VARS']['HTTP_ACCEPT']

text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
$GLOBALS['HTTP_SERVER_VARS']['HTTP_REFERER']

http://www.rinconastur.com/php/php29.php
$GLOBALS['HTTP_SERVER_VARS']['HTTP_ACCEPT_ENCODING']

gzip,deflate,sdch
$GLOBALS['HTTP_SERVER_VARS']['HTTP_ACCEPT_LANGUAGE']

es-ES,es;q=0.8
$GLOBALS['HTTP_SERVER_VARS']['HTTP_ACCEPT_CHARSET']

ISO-8859-1,utf-8;q=0.7,*;q=0.3
$GLOBALS['HTTP_SERVER_VARS']['HTTP_COOKIE']

PHPSESSID=ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['HTTP_SERVER_VARS']['PATH']

/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['HTTP_SERVER_VARS']['SERVER_SIGNATURE']

$GLOBALS['HTTP_SERVER_VARS']['SERVER_SOFTWARE']

Apache/2.0.63 (Unix) mod_ssl/2.0.63 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4 PHP/5.2.11


$GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME']

www.rinconastur.com
$GLOBALS['HTTP_SERVER_VARS']['SERVER_ADDR']

72.52.140.129
$GLOBALS['HTTP_SERVER_VARS']['SERVER_PORT']

80
$GLOBALS['HTTP_SERVER_VARS']['REMOTE_ADDR']

190.82.98.194
$GLOBALS['HTTP_SERVER_VARS']['DOCUMENT_ROOT']

/home/rinconas/public_html
$GLOBALS['HTTP_SERVER_VARS']['SERVER_ADMIN']

webmaster@rinconastur.net
$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_FILENAME']

/home/rinconas/public_html/php/php30.php
$GLOBALS['HTTP_SERVER_VARS']['REMOTE_PORT']

33367
$GLOBALS['HTTP_SERVER_VARS']['GATEWAY_INTERFACE']

CGI/1.1
$GLOBALS['HTTP_SERVER_VARS']['SERVER_PROTOCOL']

HTTP/1.1
$GLOBALS['HTTP_SERVER_VARS']['REQUEST_METHOD']

GET
$GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']

$GLOBALS['HTTP_SERVER_VARS']['REQUEST_URI']

/php/php30.php
$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']

/php/php30.php
$GLOBALS['HTTP_SERVER_VARS']['PHP_SELF']

/php/php30.php
$GLOBALS['HTTP_SERVER_VARS']['REQUEST_TIME']

1338997030
$GLOBALS['HTTP_SERVER_VARS']['argv']

Array
$GLOBALS['HTTP_SERVER_VARS']['argc']

0
$GLOBALS['_REQUEST']['PHPSESSID']

ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['xyz_DOCUMENT_ROOT']

C:/ServidoresLocales/Apache/htdocs
$GLOBALS['mi_xyz']

$GLOBALS['xyz_SERVER_ROOT']

C:/ServidoresLocales/Apache/
$GLOBALS['xyz_INSTALL']

C:/ServidoresLocales/
$GLOBALS['xyz_DIR_INSTALL']

ServidoresLocales
$GLOBALS['ver']

ver.php?URL=
$GLOBALS['ver_extension']

.php
$GLOBALS['extension']

.php
$GLOBALS['prefijo']

$GLOBALS['incluye']

general.inc.php
$GLOBALS['prefx']

$GLOBALS['prefx1']

$GLOBALS['prefx0']

$GLOBALS['opcion']

I
$GLOBALS['anterior']

php29.php
$GLOBALS['siguiente']

php31.php
$GLOBALS['clave']

php31.php
$GLOBALS['nombre']

argc

$GLOBALS['nombre1']

nombre
$GLOBALS['valor']

ed3f35bf913ecbae9d18c30daff4f6e8
$GLOBALS['nombre2']

PHPSESSID

Otras variables Valores de las variables


Cuando hablbamos de las variables y nos referamos a su mbito decamos que las variables definidas dentro de una funcin pierden sus valores en el momento en el que abandonemos el mbito de esa funcin, es decir, cuando finaliza su ejecucin. Decamos tambin que si el mbito en el que hubiera sido definida fuera externo a una funcin los valores slo se perderantemporalmente mientras durara la eventual ejecucin de las instrucciones de aquella y que, una vez acabado ese proceso, volvan a recuperar sus valores. Bajo estas condiciones, si invocramos repetidamente la misma funcin obtendramos cada vez el mismo resultado porque las posibles modificaciones que pudieran haberse producido (a travs de las instrucciones contenidas en la funcin) en sus valores se perderan cada vez que abandonramos la funcin con lo cual, cada una de las llamadas sucesivas restablecera el valor inicial.

Variables estticas
Para poder conservar el ltimo valor de una variable definida dentro de una funcin basta con definirla como esttica. La instruccin que permite establecer una variable como esttica es la siguiente: static nombre = valor;

Por ejemplo: si la variable fuera $a y el valor inicial asignado fuera 3 escribiramos: static $a=3; La variable conservar el ltimo de los valores que pudo habrsele asignado durante la ejecucin de la funcin que la contiene. No retomar el valor inicial hasta que se actualice la pgina.

Ejemplo de variables estticas


<?php # Observa que hemos prescindido de los encabezados HTML. # No son imprescindibles para la ejecucin de los scripts /* Escribamos una funcin y llammosla sinEstaticas Definamos en ella dos variables sin ninguna otra especificacin e insertemos las instrucciones para que al ejecutarse se escriban los valores de esas variables */ function sinEstaticas(){ # Pongamos aqu sus valores iniciales $a=0; $b=0; # Imprimamos estos valores iniciales echo "Valor inicial de $a: ",$a,"<br>"; echo "Valor inicial de $b: ",$b,"<br>";

/* Modifiquemos esos valores sumando 5 al valor de $a y restando 7 al valor de $b. $a +=5 y $b -=7 sern quienes haga esas nuevas asignaciones de valor ya lo iremos viendo, no te preocupes */ $a +=5; $b -=7; # Visualicemos los nuevos valores de las variables echo "Nuevo valor de $a: ",$a,"<br>"; echo "Nuevo valor de $b: ",$b,"<br>"; } # Escribamos ahora la misma funcin con una modificacin que ser # asignar la condicin de esttica a la variable $b # Llamemos a esa funcin: conEstaticas function conEstaticas(){ # Definimos $b como esttica $a=0; static $b=0; echo "Valor inicial de $a: ",$a,"<br>"; echo "Valor inicial de $b: ",$b,"<br>"; $a +=5; $b -=7; echo "Nuevo valor de $a: ",$a,"<br>"; echo "Nuevo valor de $b: ",$b,"<br>"; } # Insertemos un texto que nos ayude en el momento de la ejecucin print ("Esta es la primera llamada a sinEstaticas()<br>");

# Invoquemos la funcin sinEstaticas; sinEstaticas(); # Aadamos un nuevo comentario a la salida print ("Esta es la segunda llamada sinEstaticas()<br>"); print ("Debe dar el mismo resultado que la llamada anterior<br>"); # Invoquemos por segunda vez sinEstaticas; sinEstaticas(); # Hagamos ahora lo mismo con la funcin conEstaticas print ("Esta es la primera llamada a conEstaticas()<br>"); conEstaticas(); print ("Esta es la segunda llamada a conEstaticas()<br>"); print ("El resultado es distinto a la llamada anterior<br>"); conEstaticas(); ?>

ejemplo16.php

Variables de variables
Adems del mtodo habitual de asignacin de nombres a las variables -poner el signo $ delante de una palabra-, existe la posibilidad de que tomen como nombre el valor de otra variable previamente definida. La forma de hacerlo sera esta: $$nombre_variable_previa;

Veamos un ejemplo. Supongamos que tenemos una variable como esta: $color="verde";. Si ahora queremos definir una nueva variable que utilice como nombre el valor (verde) que est contenido en la variable previa ($color), habramos de poner algo como esto: $$color="es horrible";

Si se tratara de visualizar el valor de esta nueva variable podramos hacerlo de una de estas tres maneras: print $$color; o print ${$color}; o tambin print $verde;

Cualquiera de las instrucciones anteriores nos producira la misma salida: es horrible. Podemos preguntarnos cmo se justifica que existan dos sintaxis tan similares como $$color y ${$color}? Qu pintan las llaves?. La utilizacin de las llaves es una forma de evitar situaciones de interpretacin confusa. Supongamos que las variables tienen un nombre un poco ms raro. Por ejemplo que $color no se llama as sino $color[3] (podra ser que $color fuera un array una lista de colores y que esta variable contuviera el tercero de ellos). En este supuesto, al escribir: print $$color[3] cabra la duda de si el nmero 3 pertenece (es un ndice) a la variable $color o si ese nmero corresponde a $$color. Con print ${$color[3]} no habra lugar para esas dudas. Estaramos aludiendo de forma inequvoca a 3 como ndice de la variable $color.

Qu ocurre cuando la variable previa cambia de valor?


Cuando la variable utilizada para definir una variable de variable cambia de valor no se modifica ni el nombre de esta ltima ni tampoco su valor. Puedes ver este concepto, con un poco ms de detalle, en el cdigo fuente del ejemplo.

<?php # Definamos una variable y asignmosle un valor $color="rojo"; # Definamos ahora una nueva variable de nombre variable # usando para ello la variable anterior $$color=" es mi color preferido"; # Veamos impresos print ( "El color #o tambin print ( "El color # o tambin print ( "El color los contenidos de esas variables ".$color. $$color ."<br>"); ".$color. ${$color}."<br>"); ".$color. $rojo."<br>");

# advirtamos lo que va a ocurrir al visualizar la pgina print ("Las tres lneas anteriores deben decir lo mismo<br>"); print ("Hemos invocado la misma variable de tres formas diferentes<BR>");

# cambiemos ahora el nombre del color $color="magenta"; /* La variable $rojo seguir existiendo. El hecho de cambiar el valor a $color no significa que vayan a modificarse las variables creadas con su color anterior ni que se creen automticamente variables que tengan por nombre el nuevo valor de $color

*/

# Pongamos un mensaje de advertencia para que sea visualizado en la salida print ("Ahora la variable $color ha cambiado a magenta<br>"); print ("pero como no hemos creado ninguna variable con ese color<br>"); print ("en las lineas siguientes no aparecer nada <br>"); print ("detrs de la palabra magenta <br>"); print ("solo un mensaje de error advirtiendo que la variable no existe<br>"); /* para evitar ese mensaje de error basta con anteponer el smbolo @ a las dos instrucciones print siguientes # Escribimos los print advertidos @print (" El color ".$color.$$color."<br>"); @print (" El color ".$color.${$color}."<br>"); # Comprobemos que la variable $rojo creada como variable de variable # cuando $color="rojo" an existe y mantiene aquel valor print ("Pese a que $color vale ahora ".$color."<br>"); print ("la vieja variable $rojo sigue existiendo <br>"); print ("y conserva su valor. Es este: ".$rojo); ?>
ejemplo17.php Con mensaje de error ejemplo18.php Sin mensajes de error

Insercin de smbolos como elementos de texto


Tanto PHP como los navegadores hacen interpretaciones como smbolos del lenguaje de algunos caracteres especiales tales como$, ", o <, que cuando se pretendieran incluir como elementos no se visualizaran en pantalla. Cuando pretendamos que aparezcan escritos tendremos que indicarlo de una forma especial. En este enlace podrs ver la forma de hacerlo.

Tipos de variables
Tipos de variables
Ya hemos comentado que en PHP no es necesaria una definicin previa del tipo de variables. Segn los valores que se les vayan asignando, las variables podrn cambiar de tipo de modo automtico y se irn adaptando a los valores que contengan en cada momento. Las variables en PHP pueden ser de tres tipos: Enteras (tipo Integer) De coma flotante (tipo Double) Cadenas (tipo String)

Cualquier nmero entero cuyo valor est comprendido entre 2

31

ser interpretado por PHP como de tipo Integer.

Si el valor de una variable es un nmero decimal o siendo entero desborda el intervalo anterior, bien por asignacin directa o como resultado de una operacin aritmtica, PHP la convierte a tipo Double. Cualquier variable a la que se le asigne como valor el contenido de una cadena de caracteres (letras y/o nmeros delimitados por comillas) es interpretada por PHP como tipo String. En el cuadro siguiente podemos ver los tres tipos de variables que utiliza PHP. Las variables en PHP
Tipo Ejemplo Valor mximo Valor mnimo Observaciones Cualquier valor numrico entero (dentro de este intervalo) que se asigne a una variable ser convertido a este tipo

Integer $a=1234 2147483647 -2147483647

Double $a=1.23 una variable la convertir a este tipo String $a="123" convertir a este tipo

Cualquier valor numrico decimal, o entero fuera del intervalo anterior, que se asigne a Cualquier valor entrecomillado (sean nmeros o letras) que se asigne a una variable la

Determinacin de tipos de variables


PHP dispone de la funcin: gettype(variable) dnde variable es el nombre de la variable, devuelve una cadena de caracteres indicando el tipo de la variable que contiene.La cadena devuelta por esta funcin puede ser: Integer, double o string. Dado que PHP gestiona las variables de forma automtica y modifica los tipos de acuerdo con los valores que va tomando durante la ejecucin del script, este valor puede ser distinto segn el punto del script dnde se ejecute la funcin. En esta tabla tienes algunos ejemplos de aplicacin de esa funcin. Puedes observar en la columna Sintaxis que para visualizar el resultado anteponemos echo a gettype. Es decir, le indicamos a PHP que muestre el resultado obtenido al determinar el tipo de variable. Ejemplos de determinacin del tipo de una variable
Variable Sintaxis echo gettype($a1) echo gettype($a2) echo gettype($a3) echo gettype($a4) echo gettype($a5) echo gettype($a6) echo gettype($a7) echo gettype($a8) echo gettype($a9) echo gettype($a10) Devuelve

$a1=347 $a2=2147483647 $a3=-2147483647 $a4=23.7678 $a5=3.1416 $a6="347" $a7="3.1416" $a8="Solo literal" $a9="12.3 Literal con nmero" $a10=""

integer integer integer double double string string string string string

Forzado de tipos de variable


PHP permite forzar los tipos de las variables. Eso quiere decir que se puede obligar a PHP a asignar un tipo determinado a una variable determinada, siempre que los valores que contenga estn dentro del rango del nuevo tipo de variable. Los tipos se pueden forzar tanto en el momento de definir la variable como en un momento posterior.

Forzado y asignacin simultnea de valores


Al asignar un valor a una variable, se puede forzar su tipo de la siguiente forma. Si deseamos que la variable pase a ser tipo de doublebasta con anteponer a su valor entre parntesis tal como se indica una de las expresiones siguientes: (double), (real) o (float). Por ejemplo, tanto con $a=((double)45); como con $a=((float)45); o con $a=((real)45); se producira el mismo resultado: convertir la variable $a a tipo Double. Para forzar una variable a tipo Integer podemos anteponer a su valor una de estas expresiones: (integer), o (int). Por ejemplo: $b=((integer)4.5); o $b=((int)45); produciran el mismo efecto: convertir la variable $b a tipo Integer. Para forzar una variable a tipo String basta con anteponer a su valor (entre parntesis): (string). Por ejemplo: $c=((string)4.5); convertira la variable $c a tipo String. Forzado de tipo de variable
Variable Sintaxis echo gettype((real)$a1) echo gettype((double)$a2) echo gettype((float)$a3) echo gettype((int)$a4) echo gettype((integer)$a5) echo gettype((double)$a6) echo gettype((int)$a7) echo gettype((string)$a7) echo gettype((double)$a8) echo gettype((int)$a9) Devuelve

$a1=347 $a2=2147483647 $a3=-2147483647 $a4=23.7678 $a5=3.1416 $a6="347" $a7="3.1416" $a7="3.1416" $a8="Solo literal" $a9="12.3 Literal con nmero"

double double double integer integer double integer string double integer

Cuidado! Al modificar los tipos de variables pueden modificarse sus valores. Si forzamos a entera una variable que contenga un nmero decimal se perdera la parte decimal y la variable modificada solo contendra el valor de la parte entera. Si tratamos de convertir a numrica una variable alfanumrica el nuevo valor sera cero.
Nuevos valores de la variable
Valor inicial Sintaxis echo ((real)$a1) echo ((double)$a2) echo ((float)$a3) echo ((integer)$a5) echo ((double)$a6) echo ((int)$a7) echo ((string)$a7) echo ((int)$a8) echo ((double)$a9) Nuevo valor

$a1=347 $a2=2147483647 $a3=-2147483647 $a4=23.7678 $a5="3.1416" $a6="347" $a7="3.1416" $a8="Solo literal" $a9="12.3 Literal con nmero"

347 2147483647 -2147483647 23 3.1416 347 3.1416 0 12.3

$a9="12.3 Literal con nmero" $a10=""

echo ((int)$a9) echo ((int)$a10)

12 0

Forzado de tipos en variables ya definidas


La forma ms aconsejable de forzado de tipos en variables que ya estuvieran definidas previamente, es el uso de la siguiente instruccin: settype( var, tipo) donde var es el nombre de la variable cuyo tipo pretendemos modificar y tipo una expresin que puede contener (entre comillas) uno de estos valores: 'double', 'integer', o 'string' segn se trate de forzar a: coma flotante, entero, o cadena. Un ejemplo podra ser este: settype($a,'integer') que convertira a tipo entero la variable $a. La ejecucin de la instruccin settype devuelve (da como resultado) un valor que puede ser: true o false (1 0) segn la conversinse haya realizado con xito o no haya podido realizarse. Aqu tienes algunos ejemplos del uso de esa funcin. La tabla est organizada en bloques de tres filas que corresponden a la ejecucin de tres instrucciones y a la visualizacin del resultado de cada una de ellas. El resultado de settype primera fila solo podr ser 1 0 segn la instruccin se haya ejecutado con xito o no haya podido realizarse. En la segunda fila comprobamos el nuevo tipo de variable obtenida mediante la ejecucin de la instruccin anterior y en la terceravisualizamos los nuevos valores de la variable, que pueden haber cambiado como consecuencia del cambio de tipo. Forzado de tipos con settype()
Variable Sintaxis echo (settype($a1,'double') Devuelve

1 double 347 1 double 2147483647 1 double -2147483647 1 integer 23 1 integer 3 1 double 347 1 integer 3 1 double

$a1=347

echo gettype($a1) echo $a1 echo (settype($a2,'double')

$a2=2147483647

echo gettype($a2) echo $a2 echo settype($a3,'double')

$a3=-2147483647

echo gettype($a3) echo $a3 echo settype($a4,'integer')

$a4=23.7678

echo gettype($a4) echo $a4 echo settype($a5,'integer')

$a5=3.1416

echo gettype($a5) echo $a5 echo settype($a6,'double')

$a6="347"

echo gettype($a6) echo $a6 echo settype($a7,'integer')

$a7="3.1416"

echo gettype($a7) echo $a1

$a8="Solo literal"

echo settype($a8,'double') echo gettype($a8)

echo $a8 echo settype($a9,'integer')

0 1 integer 12

$a9="12.3 Literal con nmero"

echo gettype($a9) echo $a9

Operaciones con distintos tipos de variables


PHP permite la realizacin de operaciones aritmticas con cualquiera de los tres tipos de variables y adeca el resultado al tipo ms apropiado. En la tabla puedes ver algunos ejemplos, pero, en resumen, ocurre lo siguiente: Al operar con dos enteros, si el resultado est dentro del rango de los enteros, devuelve un entero. Si al operar con dos enteros el resultado desborda el rango entero, convierte su valor, de forma automtica, al tipo coma flotante Al operar un entero con una variable tipo coma flotante el resultado es de coma flotante. Al operar con una cadena lo hace como si se tratara de un entero. Si hay caracteres numricos al comienzo, los extrae (hasta que aparezca un punto o un carcter no numrico) y los opera como un nmero entero. Si una cadena no comienza por un carcter numrico PHP la operar tomando su valor numrico como CERO. La tabla siguiente contiene en cada fila los valores asignados a dos variables (A y B) y el resultado de la suma de ambas. A continuacin se recogen los tipos de variable de cada una de ellas y el del resultado. El tipo de este ltimo generado por PHP estar condicionado por el valor del resultado de cada una de las operaciones. Resultados de operaciones y tipos de variables resultantes
Valores A B A+B Tipos de variables A B A+B

12 12 -12 12 1.2456 1.2456 12 1.2456 12 12 1.2456 1.2456 abc abc 12abc

16 2147483647 -2147483640 1.2456 12 123.4567 abc abc 12abc 12.34567abc 12.34567abc 12.3e2abc 12abc 12.34567abc 12.34567abc

28 2147483659 -2147483652 13.2456 13.2456 124.7023 12 1.2456 24 24.34567 13.59127 1231.2456 12 12.34567 24.34567

integer integer integer integer double double integer double integer integer double double string string string

integer integer integer double integer double string string string string string string string string string

integer integer integer double double double integer double integer double double double integer double double

Utilizando formularios PHP dinmico


Hasta el momento, PHP slo nos ha servido para escribir una serie de scripts y ver los resultados de su ejecucin pero an no hemos hecho mencin alguna a la manera en la que puede establecerse un dilogo (interaccin) entre cliente y el servidor que, en definitiva, es la razn de ser de las pginas dinmicas.

Cuando se trata de pginas estticas la comunicacin est muy restringida. El cliente hace una peticin (escribe el nombre de una pgina en la barra de direcciones del navegador) y el servidor se limita a devolver los contenidos de esa pgina. Un primer paso para mejorar es esa comunicacin ser que el cliente especifique algo ms en su peticin y que el servidor interprete esa informacin complementaria. Ese algo ms puede incluirse en la barra de direcciones con la siguiente sintaxis: pagina.php?nombre1=valor1&nombre2=valor2, ...

dnde pagina.php es la direccin de una pgina que contiene scripts PHP y dnde ? es un carcter obligatorio que indica que detrs de l se incluye ms informacin. Esa informacin estar formada por parejas nombre - valor enlazadas por un signo = y separadas entre s por el smbolo &. De esa forma el servidor entendera la peticin de la siguiente forma: Vete a la pgina pagina.php, mira los scripts PHP, asigna a las variables nombre1, nombre2 etctera los valores valor1, valor2,... ejecuta los scripts con esos valores y devulveme los resultados. Observars que los nombres de las variables nunca llevan el signo $ y que los valores de las variables sean nmeros o cadenastampoco se escriben nunca entre comillas. Algunos caracteres especiales (& por ejemplo) no pueden escribirse directamente dado que se prestan a confusin dando lugar a la duda de si habran de intepretarse como un valor como el smbolo de unin. En esos casos es necesario sustituir el carcter por su codificacin URL que representa cada carcter anteponiendo el signo % al valor de su cdigo ASCII expresando en formato hexadecimal. Eneste enlace tienes una tabla de conversin. Se pueden incluir tantos nombre = valor como se desee. La nica restriccin es la longitud mxima permitida por el mtodo GET (el utilizado en este caso) que se sita en torno a los 2.000 caracteres.

Recepcin de datos
Cuando es recibida por el servidor la peticin de un documento con extensin .php en la que tras el signo ? se incluyen una o varias parejas nombre = valor, los nombres de las variables y sus valores respectivos se incluyen siempre, de forma automtica, en variables predefinidas de dos tipos: $_GET['nombre1']=valor1, $_GET['nombre2']=valor1, etctera, en las que nombre1, nombre2, ... coinciden exactamente con nombres especificados en las peticin y los valores asignados a estas variables tambin coinciden con los recibidos, junto con cada nombre, a travs de la peticin. $_REQUEST['nombre1']=valor1, $_REQUEST['nombre2']=valor1 recoge los mismos valores que la anterior $_GET. Esta aparente duplicidad de informacin tiene una funcionalidad aadida que veremos un poco ms adelante La variables anteriores tienen una sintaxis un poco engorrosa. Por eso, las versiones ms recientes de PHP incluyen una nueva funcin que puede agregar algo de funcionalidad. Es la siguiente: extract(array asociativo)

que crea de forma automtica variables con los nombres de todos los indices del array les asigna el valor de ese elemento del array. Es decir, si hemos recibido valores como $_GET['nombre1']=7 y $_GET['nombre2']='pepe' e incluimos en el script la funcin extract($_GET)PHP crear de forma automtica las variables $nombre1=7 y $nombre2='pepe'. Mediante extract($_REQUEST) obtendran los mismos resultados. En definitiva, la funcin extract() no hace otra cosa que crear variables PHP con idntico nombre al indicado en la peticin. Hay configuraciones de PHP en las que no es necesario utilizar la funcin extract(). Cuando el fichero php.ini tiene configurada la directiva register_globals=ON las variables del tipo: $nombre1=valor1, $nombre2=valor2, etctera se crearan de forma automtica al ser recibida la peticin del cliente.

Cuidado! La directiva register_globals ha evolucionado mucho a travs de las distintas versiones de PHP. En las versiones ms antiguas vena configurada, por defecto, con el valor ON. Actualmente viene configurada, tambin por defecto

comoOFF y se comenta que en futuras versiones de PHP su valor seguir siendo OFF pero ya no ser posible modificarla. Por ello, quiz lo ms prudente escribir nuestro cdigo pensando siempre que su configuracin es OFF y adems es inmodificable.

Veamos algunos ejemplos.

<?php /* Empezaremos utilizando $_GET['a'], $_GET['b' */ # Pongamos un comentario de advertencia. Recuerda que <br> # sirve para insertar un salto de lnea en la salida print ("Este resultado es el que utiliza \$_GET<br>"); print ($_GET['a']." x ".$_GET['b']." = ".$_GET['a']*$_GET['b']); /* Ahora trataremos de comprobar que tambin podemos utilizar la superglobal $_REQUEST como $_REQUEST['a'] y $_REQUEST['b'] con iguales resultados que las anteriores */ # Un comentario para identificar el origen del resultado print("<br>El resultado siguiente ha sido generado usando \$_REQUEST <br>"); print $_REQUEST['a']." x ".$_REQUEST['b']." = "; print $_REQUEST['a']*$_REQUEST['b']; ?>
ejemplo19.php ejemplo20.php

Si pulsas el enlace del ejemplo19 vers que te aparece una retahila de mensajes de advertencia. Es lgico que as sea. El script necesita los valores de las variables $a y $b. Como no recibe nada los ha de considerar con valor cero y, a la vez, dado que PHP tiene configurada la gestin de errores de forma muy estricta nos advierte que esas variables no han sido inicializadas. Si escribieras ejemplo19.php?a=21&b=456 todo funcionara correctamente. No habra lugar al mensaje de advertencia porque las variables ya tienen contenido. Para evitar la visualizacin de los mensajes de advertencia existen diferentes posibilidades. Adems de las mencionadades cuando estudibamos las variables las tienes comentadas en este enlace tenemos la opcin de modificar el script anteponiendo a las instrucciones print (las que pueden dar el mensaje de error cuando se ejecuten sin asignar valores a las variables) el smbolo @. Mediante ese smbolo (@) inhibimos la aparicin del mensaje de error al ejecutarse la instruccin a la que precede. Eso es lo que hemos hecho en elejemplo20. Vers que al ejecutarlo (aqu est su cdigo fuente) ya no aparece el mensaje de error. Como es lgico, al asignar valores a las variables escribiendo en la barra de direcciones del navegador la siguiente direccin:ejemplo20.php?a=21&b=456, (o pulsemos directamente en este enlace) el resultado no diferira en nada del obtenido con el ejemplo19.

Cuidado! Aqu, ms que nunca, conviene reiterar, una vez ms, los errores de sintaxis ms frecuentes: Los nombres de variables son distintos si se cambian maysculas y minsculas. Pon mucho cuidado en escribirlos correctamente. Los nombres de las variables predefinidas, tales como $_GET, etctera van en maysculas. No olvides poner punto y coma al final de cada lnea de instrucciones. Presta atencin a la apertura/cierre de comillas y mucha ms atencin an si se trata de comillas anidadas. En este caso procura usar (") para las exteriores y (') para las interiores.

Probemos otras de las opciones. Utilicemos la funcin extract para leer los datos recibidos.

<?php /* al incluir extract se crearn variables automticas con los nombres incluidos a travs de la barra de direcciones

del navegador */ extract($_GET); /* Escribamos una instruccin, que imprima en pantalla el valor de una de las variables extraidas ($a), una "x" que har funciones de aspa en la presentacin, otra variable ($b), el signo igual y $a*$b que es el producto de ambas variables El simbolo de multiplicar es (*) anteponemos al print el simbolo @ para evitar que aparezca mensaje de error por variable no definida @print ($a." x ".$b." = ".$a*$b); # Aadamos una bobadilla, para animar... ;-) print ("<br> Acabamos de usar la funcin extract!!"); ?>
ejemplo21.php ejemplo22.php

*/

Ejecuta este ejemplo (no aparecern mensajes de advertencia porque hemos incluido los @ que los inhiben) y observa lo que aparece. Slo x =0? y la otra lnea? El resultado es lgico. No hemos asignado valores a las variables $a y $b y por eso no escribi su valor. Sin embargo, a la hora de multiplicar -recuerda que una variable vaca es interpretada como cero a la hora de hacer operaciones la interpret como cero y con muy buen criterio nos respondi que cero por cero es cero. Escribamos ahora la direccin: ejemplo21.php?a=13&b=7, (tambin puedes pulsar en este enlace) y podremos comprobar que 13 x 7 = 91 . Observa tambin que ahora no aparece ningn mensaje de error porque hemos antepuesto @ a la instruccin print. Hagamos un nuevo experimento. Probemos ejemplo22.php?a=13&b=7 y veamos que el resultado no es el esperado. El ejemplo22 es muy similar al ejemplo21 (puedes ver aqu su cdigo fuente) pero tiene una diferencia importante. Hemos comentado la lnea que contiene la funcin extract. Por tanto esta ya no se ejecuta. Lo que realmente ocurre es que no lee los valores de las variables $a y $b porque para poder leerlas directamente se requera que la directiva register_globals de php.ini estuviera ON y, por defecto, esta directiva viene configurada como register_globals=Off. Si pruebas a cambiar esa configuracin, reinicias el servidor y pulsas de nuevo en el enlace, vers que esta vez si ha recibido los valores de a y b y nos ha dado el resultado de la operacin.

Cuidado! En modo local puedes establecer las configuraciones de php.ini a tu antojo que te permite utilizar cualquiera de las opciones de transferencia de variables. Pero, si pretendes publicar tus pginas utilizando un hosting ajeno debes usar la opcin de mayor compatibilidad se son, sin duda alguna, $_GET, $_REQUEST complementadas, si lo estimas ms cmodo con la funcin extract. Ten en cuenta que all no vas a poder modificar las configuraciones y de no tener en cuenta estos aspectos, puedes verte obligad@ a modificar tu cdigo fuente para adecuarlo a la configuracin de tu hosting.

Envo a travs de formularios


La interaccin clienteservidor que acabamos de ver resulta incmoda en su uso y no demasiado esttica. Hay una segunda opcin la de uso ms frecuente que es la utilizacin de formularios que no son elementos propios de PHP actan del lado del cliente siendo su estudio es ms propio del mbito de HTML que de PHP. No obstante por si te fuera necesario aqu tienes un formulario, en el que se comenta la sintaxis de sus elementos ms comunes.

Un ejemplo formulario

<html> <head>

</head> <body> <!-- Un formulario debe empezar siempre con una etiqueta de este tipo <form ...> dentro de la cual obligatorio indicar con esta sintaxis action='nombre.extension' el nombre de la pgina destinataria de la informacin que se incluya en el formulario. nombre.extension debe contener el nombre (o la ruta completa en el caso de que estuviera en un directorio o hosting distinto del que alberga el documento que contiene el formulario desde el que se realiza la peticin) Es opcional incluir (tambin dentro de la etiqueta <form ...>) method que puede tener dos valores method='GET' method='POST' Por defecto (cuando no se indica) se interpretar que method='GET' Tambin es opcional -a los efectos de PHP- incluir name. Ese valor es til cuando se incluyen scripts del lado del cliente del tipo JavaScript //--> <form name='mi_formulario' action='ejemplo26.php' method='post'> <!-- Pueden incluirse textos dentro del formulario --> Escribe tu nombre: <!-- Uno de los tipos de campos posibles es el tipo texto. Su sintaxis (hablamos de HTML) requiere la etiqueta <input type='text'> que indica que el contenido ser texto. Esta etiqueta debe incluir obligatoriamente un name='nombre' en el que pueden usarse caracteres alfabticos, sin tildes ni ees y sin espacios. Salvo excepciones que veremos ms adelante el nombre ha de ser nico y distinto para cada elemento del formulario. Tambin dentro de la etiqueta <input type='text'> puede incluirse value='' que puede no contener nada tal como ocurre aqu o contener el texto que, por defecto, queremos que aparezca en ese campo al cargar el formulario. Tambin puede conteenr (es opcional) size=xx. Su utilidad es la de ajustar el tamao de la ventana al nmero de caracteres que se indiquen mediante xx //-> <input type='text' name='nombre' value='' size=15><br> Escribe tu clave: <!-- <input type='password'> solo se diferencia del anterior en que en el momento de rellenarlo se sustituyen los carecteres visualizados (no el contenido) por asteriscos //--> <input type='password' name='clave' value=''><br> Elige tu color de coche favorito:<br> Los <input type='radio'> permite optar entre varios valores posibles. Habr que repetirlos tantas veces como opciones queramos habilitar. Todos los input correspondientes a la misma opcin deben tener el mismo nombre (name) value='xxxxx' deber tener un valor distinto en cada uno de ellos. El valor (loquesea) de la opcin marcada es que ser transferido a travs del formulario Si queremos que una opcin aparezca marcada (por defecto)al cargar el formulario, deberemos incluir en su etiqueta la palabra checked <!--

Los contenidos de value no se visualizan en el navegador por lo que conviene incluir una descripcin de los valores despus de cerrar la etiqueta de cada uno de esos input. Al enviar el formulario solo se transmite el value de la opcin seleccionada //--> <input type='radio' name='color' value='Rojo'>Rojo</br> <input type='radio' checked name='color' value='Verde'>Verde</br> <input type='radio' name='color' value='Azul'>Azul</br> Elige los extras:<br> <!-- Cada uno de los <input type='checkbox'> requiere un nombre distinto (name) y un valor (value) Pueden marcarse uno, varios, todos o ninguno. Si queremos que una casilla aparezca marcada (por defecto) al cargar el formulario, deberemos incluir en su etiqueta la palabra checked Solo sern transferidos a travs del formulario los nombres y valores de aquellos cuya casilla est marcada. Los contenidos de value no se visualizan en el navegador por lo que conviene incluir una descripcin de los valores despus de cerrar la etiqueta de cada input //--> <input type='checkbox' name="acondicionado" value="Aire">Aire acondicionado<br> <input type='checkbox' checked name="tapiceria" value="Tapicieria">Tapiceria en piel<br> <input type='checkbox' name="llantas" value="aluminio">Llantas de aluminio<br> <br>Cual es el precio mximo que estaras dispuesto a pagar? <!-- La etiqueta <input type='select'> requiere un nombre y una etiqueta de cierre </select> Entre ambas -apertura y cierre- deben incluirse las diferentes opciones entre las etiquetas <option>valor<option> Al enviar el formulario se transmite lo contenido despus de opcin en la seleccionada salvo que dentro de la propia etiqueta opcin se incluya un value. Si dentro de una etiqueta option escribimos selected ser esa la que aparezca seleccionada ,por defecto, al cargarse el formulario//--> <select name="precio"> <Option>Menos de 6.000 euros</option> <Option>6.001 - 8.000 euros</option> <Option selected >8.001 - 10.000 euros</option> <Option value=11634.52>10.001 - 12.000 euros</option> <Option>12.001 - 14.000 euros</option> <Option>Ms de 14.000 euros</option> </select> <!-- Las reas de texto deben tener una etiqueta de apertura <textarea name='checkbox'> seguida de una etiqueta de cierre </textarea> Dentro de la etiqueta de apertura puede incluirse rows=xx (indicar el nmero de filas) cols=yy (indicar el ancho expresado en nmero de caracteres) y opcionalmente un value='lo que sea...' que puede contener el texto que -por defecto- pretendemos que aparezca en ese espacio al cargar el formulario //--> <br> Escribe aqu cualquier otro comentario:<br> <textarea rows=5 cols=50 name='texto'></textarea><br>

<!-- El <input type='hidden'> permite insertar en un formulario una valor oculto que no requiere ser cumplimentado por el usuario y que no aparece visible en el documento. Requiere un name y un value //--> <input type="hidden" name='oculto' value='Esto ira oculto'><br> <!-- El <input type='submit'> es el encargado de ejecutar la action incluida en la etiqueta de apertura del formulario. Sera la llamada a la pgina que se indica en la action El texto que se incluya en su value ser el que se visualice en el propio botn de envio //--> <input type="submit" value="enviar"> <!-- El <input type='reset'> permite borrar todos los contenidos del formulario y reestablecer los valores por defecto de cada campo //--> <input type="reset" value="borrar"> <!-- La etiqueta </form> es la etiqueta (obligatoria) de fin del formulario </form> </body> </html> //-->

Interpretacin de los datos recibidos a travs de formularios


Igual que ocurra en el caso anterior, los datos enviados a travs de un formulario son recogidos en diferentes tipos de variables predefinidas. Ahora se aade una nueva particularidad. Existe la posibilidad de dos mtodos (method) de envo: GET o POST. En el caso anterior decamos que se utilizaba el mtodo GET, pero en el caso de los formularios son posibles ambos mtodos. Conviene tenerlo en cuenta.

Mtodo GET
No se diferencia en nada de lo descrito para el supuesto anterior. Utiliza las mismas variables predefinidas ($_GET y $_REQUEST), las utiliza con idntica sintaxis y se comporta de igual forma en lo relativo a las opciones de register_globals. Los nombres de las variables son en este caso, los incluidos como name en cada una de las etiquetas del formulario. Respecto a los valores recogidos del formulario seran los siguientes. En los casos de campos tipo: text, password y textarea seran los valores introducidos por el usuario en cada uno de ellos. En el caso de los campos tipo radio en el que varias opciones pueden tener el mismo nombre recogera el valor indicado en la casilla marcada; mientras que si se trata de campos tipo checkbox se transferiran nicamente las variables y los valores que corresponden a las casillas marcadas. Si se tratara de un campo oculto tipo hidden se transferira el valor contenido en su etiqueta y, por ltimo, en el caso del select sera transferido como valor de la variable la parte del formulario contenida entre las etiquetas <option></option> de la opcin seleccionada salvo que, dentro de la propia etiqueta option se incluya un valor mediante value=xxxxx.

Mtodo POST
En el caso de que el mtodo de envo sea POST hay una diferencia a tener en cuenta en cuanto a las variables que recogen la informacin. Ahora ser la variable superglobal $_POST['nombre'] la que reemplace a $_GET['nombre'] usado en el caso del mtodo GET. Si register_globals est en On el comportamiento de las variables directas es idntico al comentado para el caso de GET.

La opcin REQUEST
La variable superglobal $_REQUEST['nombre'] ana las funcionalidades de $_GET y $_POST y que recoge tanto los valores transferidos mediante el mtodo GET como mediante POST.

Identificacin del mtodo de envo


PHP recoge en una variable el mtodo utilizado para enviar los datos desde un formulario. Se trata de la variable: $_SERVER['REQUEST_METHOD']

que devuelve una cadena (GET POST) que especifica el mtodo de envo utilizado.

Diferencias ente los mtodos GET y POST


Las diferencias entre uno y otro mtodo son las siguientes: Mtodo GET Al ser enviado el formulario se carga en el navegador la direccin especificada como action, se le aade un ? y a continuacin se incluyen los datos del formulario. Todos los datos de la peticin van a ser visibles en la barra de direcciones del navegador. nicamente son aceptados los caracteres ASCII. Tiene una limitacin en el tamao mximo de la cadena que contiene los datos a transferir. En IE esa limitacin es de 2.083 caracteres. Suele ser utilizado cuando los datos no producen modificaciones en el servidor tal como ocurre en consultas en bases de datos, bsquedas y similares. Mtodo POST No tiene las limitaciones indicadas para el caso de GET en lo relativo a la aceptacin de caracteres no ASCII. Los datos del formulario no se visualizan en la barra de direcciones del navegador. Este mtodo de transferencia de datos es el ms habitual cuando se utilizan formularios. Suele ser utilizado cuando los datos transferidos producen algn tipo de modificacin en los dos datos almacenados en el servidor tales como: altas en bases de datos, modificaciones, etctera.

Tipos de contenidos de los formularios


Vamos a contemplar un ltimo aspecto relativo a los formularios. Se trata de la forma de codificar los datos para su transmisin (ENCTYPE). Puede especificarse dentro de la etiqueta<form> utilizando la sintaxis: enctype='valor'. En el caso de que no se especifique, tomar el valor application / x-www-form-urlencoded, sea GET o POST el mtodo que se utilice. ENCTYPE admite tambin el valor multipart/form-data como una opcin alternativa a la anterior. Las diferencias bsicas entre ambos modos de codificacin son las siguientes: En el tipo application/x-www-form-urlencoded los nombres de control y los valores se transforman en secuencias de escape, es decir, convirtiendo cada byte en una cadena %HH, donde HH es la notacin hexadecimal del valor del byte. Adems, los espacios son convertidos en signos +, los saltos de lnea se representan como %0D%0A, el nombre y el valor se separan con el signo = y los diferentes bloques nombre/valor, se separan con el carcter &. El tipo de contenido application / x-www-form-urlencoded es utilizable cuando el volumen de datos es reducido y todos los caracteres remitidos son ASCII. En cuanto a la encriptacin tipo multipart/form-data, sigue las reglas de las transferencias MIME, que comentaremos ms adelante cuando tratemos el tema del correo electrnico.

El tipo de contenido multipart / form-data debe utilizarse en formularios que contienen archivos adjuntos, caracteres no-ASCII, y datos binarios.

Cuidado! Cuando se incluye una cadena vaca ("") como valor de action en un formulario se recargar el mismo documento como respuesta al envo del formulario.

Ejemplos de las diferentes opciones de formularios


Intentaremos ver ejemplos de las diferentes opciones. Utilizaremos un formulario idntico al descrito anteriormente dnde incluiremos como action una llamada al script ejemplo26.php (su cdigo fuente es el que puedes ver aqu debajo) y donde dnde no especificaremos ningn valor para ENCTYPE con lo cual asumir su valor por defecto, application / x-www-form-urlencoded En el cdigo fuente que ves aqu debajo intentamos leer los contenidos transferidos utilizando las diferentes posibilidades que nos ofrece PHP. Incluimos dos ejemplos cuya una nica diferencia el mtodo utilizando en el formulario. En el primero de ellos se utiliza el mtodo GET y en el segundo POST.

<?php print "Empezaremos comprobando el mtodo de envo"; print " El method que ha usado fu: ".$_SERVER['REQUEST_METHOD']."<br>"; print "Leeremos los contenidos de la superglobal \$_REQUEST"; print " Funcionar tanto con el mtodo GET como con POST"."<br>"; @print $_REQUEST['nombre']."<br>"; @print $_REQUEST['clave']."<br>"; @print $_REQUEST['color']."<br>"; @print $_REQUEST['acondicionado']."<br>"; @print $_REQUEST['tapiceria']."<br>"; @print $_REQUEST['llantas']."<br>"; @print $_REQUEST['precio']."<br>"; @print $_REQUEST['texto']."<br>"; @print $_REQUEST['oculto']."<br>"; print "Ahora leeremos los contenidos de la superglobal \$_POST"; print " Slo dar resultados cuando el mtodo sea POST"."<br>"; @print $_POST['nombre']."<br>"; @print $_POST['clave']."<br>"; @print $_POST['color']."<br>"; @print $_POST['acondicionado']."<br>"; @print $_POST['tapiceria']."<br>"; @print $_POST['llantas']."<br>"; @print $_POST['precio']."<br>"; @print $_POST['texto']."<br>"; @print $_POST['oculto']."<br>"; print "Ahora leeremos los contenidos de la superglobal \$_GET"; print " Slo dar resultados cuando el mtodo sea GET"."<br>"; @print $_GET['nombre']."<br>"; @print $_GET['clave']."<br>"; @print $_GET['color']."<br>"; @print $_GET['acondicionado']."<br>"; @print $_GET['tapiceria']."<br>"; @print $_GET['llantas']."<br>"; @print $_GET['precio']."<br>"; @print $_GET['texto']."<br>"; @print $_GET['oculto']."<br>"; print "Ahora intentaremos leer variables directas" ; print " Slo dar resultados cuando REGISTER_GLOBALS=On"."<br>"; @print $nombre."<br>"; @print $clave."<br>"; @print $color."<br>"; @print $acondicionado."<br>";

@print $tapiceria."<br>"; @print $llantas."<br>"; @print $precio."<br>"; @print $texto."<br>"; @print $oculto."<br>"; print "Incluyamos la funcin extract aplicada a \$_REQUEST"; print " de esa forma dar resultados tanto cuando el mtodo sea GET como cuando sea POST. "; print " Si la hubiramos aplicado \$_POST solo funcionara con ese mtodo."; print " Si lo hubiramos hecho \$_GET solo atendera ese mtodo"."<br>"; extract($_REQUEST); @print $nombre."<br>"; @print $clave."<br>"; @print $color."<br>"; @print $acondicionado."<br>"; @print $tapiceria."<br>"; @print $llantas."<br>"; @print $precio."<br>"; @print $texto."<br>"; @print $oculto."<br>"; ?>
Con method = POST Con method = GET

Estos dos nuevos ejemplos son modificaciones de los anteriores. Ahora hemos incluido dentro de la etiqueta <form> la opcinENCTYPE="multipart/form-data" manteniendo el resto del formulario sin ninguna modificacin.
Con method = POST Con method = GET

La seguridad en los envos de datos


El tema de la seguridad es una preocupacin constante entre los usuarios de Internet. Cuando utilizamos las tcnicas que venimos comentando en esta pgina nos referimos siempre al caso de servidores remotos corremos dos tipos de riesgo de seguridad que no estara de ms tener en cuenta. El riesgo de que la informacin sea interceptada durante el proceso de transmisin desde el cliente hasta el servidor lo compartimos con todos los dems usuarios de la Red, pero hay otro el riesgo de daos en los contenidos de nuestro espacio de servidor que esexclusivamente nuestro. La transparencia del mtodo GET es tal, que incluso muestra en el momento del envio todos los datos en la barra de direcciones del navegador. Eso permite que cualquier usuario pueda conocer a simple vista la ruta completa hasta el script, as como los nombres y valores de las variables. Cuando se usa el mtodo POST los formularios son un poco ms discretos, pero igual de transparentes. El cdigo de cualquier formulario estar accesible slo con ir a la opcin Ver cdigo fuente y all estarn de nuevo todos los datos: nombre del script, nombres de las variables, etctera, con lo que, cualquier usuario y desde cualquier sitio, puede acceder a ese script. No hara falta ni usar nuestro formulario. Bastara guardar una copia del mismo en el ordenador del visitante y despus haciendo ligersimos retoques se podra acceder a nuestro script sin necesidad de utilizar el formulario alojado en nuestro servidor. Si pensamos que uno de nuestros scripts puede estar diseado con el fin de modificar algunos de los contenidos de nuestro espacio borrar datos, por ejemplo seguramente sera cuestin de empezar a preocuparnos, y mucho ms si en nuestro servidor tenemos datosimportantes. Existen formas de evitar, o al menos reducir, este tipo de riesgos. Restringir a usuarios autorizados el uso de algunos subdirectorios es una de ellas, almacenar datos importantes fuera del directorio root del servidor es otra y el uso de algunas de las variables predefinidas como elementos de proteccin puede ser una tercera. Hacemos este comentario a ttulo meramente informativo. Por el momento nos basta con manejar los formularios, pero queremos que tengas presente la existencia de ese tipo de riesgos. Ms adelante, ve- remos la manera de tratar de evitarlos. En los

contenidos opcionales de estos materiales hemos incluido informacin relativa a la configuracin y uso de servidores seguros que pueden paliar en gran medida algunos de estos riesgos de seguridad.

Operaciones aritmticas Operaciones aritmticas


En pginas anteriores hemos podido ver que PHP permite utilizar un tipo de variables las numricas cuyos valores puedan seroperados de la misma forma que se hace con los nmeros en la vida cotidiana. Los resultados de las operaciones pueden utilizarse de forma directa o ser recogidos en una nueva variable. Si asignamos a una nueva variable el resultado de una operacin el valor contenido en ella no se modifica si cambian posteriormente los de las variables que intervinieron su creacin.

Sintaxis de print y echo


Si queremos encadenar en una sola instruccin echo print el resultado de una operacin junto con otras variables (o cadenas) esimprescindible poner entre parntesis las instrucciones de la operacin. Esta norma solo tiene dos excepciones: en caso de que el print solo contenga la propia operacin o cuando utilicemos echo y el separador sea una coma.

Operadores aritmticos
Las diferentes operaciones aritmticas se realizan en PHP utilizando la siguiente sintaxis: $a + $b

Devuelve la suma de los valores nmericos contenidos en las variables $a y $b. $a $b

Devuelve la diferencia de los valores nmericos contenidos en las variables $a y $b. $a * $b

Devuelve el producto de los valores nmericos contenidos en las variables $a y $b. $a / $b

Devuelve el cociente de los valores nmericos contenidos en las variables $a y $b. (int)($a / $b)

Devuelve el cociente entero de los valores nmericos contenidos en las variables $a y $b. $a % $b

Devuelve el resto de la divisin entera de los valores nmericos contenidos en las variables $a y $b. Sqrt($a)

Devuelve la raz cuadrada del valor nmerico contenido en la variables $a. pow($a,$b)

Devuelve el resultado de elevar el valor nmericos contenido en la variable $a a la potencia indicada en la variable $b (a ) pow($a,1/$b)

Devuelve el resultado de elevar el valor nmericos contenido en la variable $a a la potencia indicada en la variable 1/$b lo cual no es otra cosa que la raz de ndice $b de $a. Abs($a);

Devuelve el valor absoluto del valor nmerico contenido en la variable $a.

<?php # definamos dos variables numricas asignandoles valores $a=23; $b=34; /* hagamos una suma y escribamos directamente los resultados utilizando las instrucciones print y echo con todas sus posibles opciones de sintaxis */ print("La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b)."<br>"); print "La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>"; print ("La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>"); echo "La suma de $a + $b es: " . $a . "+" . $b . "=" . ($a+$b) ."<BR>"; echo "La suma de $a + $b es: " , $a , "+" , $b . "=" , ($a+$b) ."<BR>"; echo "La suma de $a + $b es: " , $a , "+" , $b , "=" , $a+$b ,"<BR>"; # guardemos ahora el resultado de esa operacin en una nueva variable $c=$a+$b; /*ahora presentemos el resultado utilizando esa nueva variable adviertiendo el la salida */ print ("Resultados recogidos en una nueva variable<br>"); print "La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>"; print ("La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>"); echo "La suma de $a + $b es: " . $a . "+" . $b . "=" . $c ."<BR>"; echo "La suma de $a + $b es: " , $a , "+" , $b . "=" , $c ."<BR>"; echo "La suma de $a + $b es: " , $a , "+" , $b , "=" , $c ,"<BR>"; /* modifiquemos ahora los valores de $a y $b comprobando que el cambio no modifica lo contenido en la variable $c */ $a=513; $b=648; print ("<br> C sigue valiendo: " . $c ."<br>"); # experimentemos con los parntesis en un supuesto de operaciones combinada # tratemos de sumar la variable $a con la variable $b # y multiplicar el resultado por $c. # Si escribimos print($a+$b*$c) nos har la multiplicacin antes que la suma print "<br>No he puesto parntesis y el resultado es: ".($a+$b*$c); # Si escribimos print(($a+$b)*$c) nos har la suma y luego multiplicar print "<br>He puesto parntesis y el resultado es: ".(($a+$b)*$c); ?>
ejemplo33.php

Operaciones aritmticas
Operacin Sintaxis $a+$b $a-$b $a*$b A B Resultado

Suma Diferencia Producto

12 12 12

-7.3 -7.3 -7.3

4.7 19.3 -87.6

Cociente Cociente entero Resto de la divisin Potencias a Potencias a


b b

$a/$b (int)($a/$b) $a%$b pow($a,$b) pow($a,$b) Sqrt($a) Sqrt($a) pow($a,(1/$b) Abs($b)

12 12 12 12 -7.3 12 -7.3 12

-7.3 -7.3 5 5 -3

-1.64383561644 -1 2 248832 -0.00257058174836 3.46410161514 NAN

Raz cuadrada Raz cuadrada Raz ensima Valor absoluto

3 -7.3

2.28942848511 7.3

Al realizar una operacin cuyo resultado no es un nmero real PHP devuelve la cadena NaN tal como puedes ver en el ejemplo de laraz cuadrada de un nmero negativo.

Redondeo de resultados
PHP dispone de tres opciones de redondeo: floor($z)

Redondeo por defecto ceil($z)

Redondeo por exceso round($z)

Redondeo tradicional Redondeos


tipo Sintaxis (int)$a (int)$a (int)$a (int)$a (int)$a (int)$a floor($a) floor($a) floor($a) floor($a) floor($a) floor($a) ceil($a) ceil($a) ceil($a) ceil($a) ceil($a) A Resultado

Parte entera Parte entera Parte entera Parte entera Parte entera Parte entera Redondeo por defecto Redondeo por defecto Redondeo por defecto Redondeo por defecto Redondeo por defecto Redondeo por defecto Redondeo por exceso Redondeo por exceso Redondeo por exceso Redondeo por exceso Redondeo por exceso

12 -7.3 -13.8546 -24.5 13.8546 24.5 12 -7.3 -13.8546 -24.5 13.8546 24.5 12 -7.3 -13.8546 -24.5 13.8546

12 -7 -13 -24 13 24 12 -8 -14 -25 13 24 12 -7 -13 -24 14

Redondeo por exceso Redondeo Redondeo Redondeo Redondeo Redondeo Redondeo

ceil($a) round($a) round($a) round($a) round($a) round($a) round($a)

24.5 12 -7.3 -13.8546 -24.5 13.8546 24.5

25 12 -7 -14 -25 14 25

Orden de operacin
Cuando una misma instruccin contiene una secuencia con varias operaciones el orden de ejecucin de las mismas sigue los mismos criterios que las matemticas. No se realiza una ejecucin secuencial sino que se respeta el orden de prioridad matemtico. Es decir, las potencias y races tienen prioridad frente a los productos y los cocientes, y estos, son prioritarios respecto a la suma y las diferencias. Igual que en matemticas se pueden utilizar los parntesis para modificar el orden de ejecucin de las operaciones, e igual que allPHP tambin permite encerrar parntesis dentro de parntesis.

Cuidado! Cuando realices operaciones combinadas, no olvides establecer mediante parntesis las prioridades que sean necesarias. No temas abusar de ellos! Te evitarn muchos problemas.

Punto flotante y precisin arbitraria


Las funciones aritmticas que estamos estudiando utilizan la sintaxis de punto flotante cuya precisin es limitada y, aunque depende del sistema, PHP tpicamente utiliza el formato de doble precisin IEEE 754, el cual puede dar un error relativo 16 mximo por aproximacin del orden de 1.11*10 . Las operaciones aritmticas ms elementales nunca van a dar grandes errores aunque la dimensin de estos podr irse incrementando a medida que se concatenar varios de esos errores simples en operaciones compuestas. Hay que tener en cuenta la existencia de fracciones que se pueden representar de forma exacta como nmeros de punto flotante en base 10 (por ejemplo 1/10 7/10) pero que carecen de esa exactitud al ser expresados en base 2 que es la usada internamente por PHP. As pues, hemos de tener cuidado al considerar nmeros de coma flotante hasta su ltimo dgito por los imprevisibles efectos sobretodo a la hora de la comparacin de esos errores en el resultado. Para operaciones matemticas que necesiten una mejor precisin PHP (innecesaria en el mbito cotidiano y limitada a casos muy puntuales del mbito cientfico) ofrece la calculadora binaria que soporta nmeros de cualquier tamao y precisin representados como cadenas. Las funciones que utilizan esa forma de clculo son las siguientes: bcadd($a,$b,c)

Devuelve la suma de los valores numricos contenidos en las cadenas $a y $b con una precisin (nmero de cifras decimales) especificada por el nmero entero especificado en el parmetro c. bcsub($a,$b,c)

Devuelve la diferencia entre los valores numricos contenidos en las cadenas $a y $b con una precisin (nmero de cifras decimales) especificada por el nmero entero especificado en el parmetro c.

bcmul($a,$b,c)

Devuelve el producto de los valores numricos contenidos en las cadenas $a y $b con una precisin (nmero de cifras decimales) especificada por el nmero entero especificado en el parmetro c. bcdiv($a,$b,c)

Devuelve el resultado de dividir los valores numricos contenidos en las cadenas $a y $b con la precisin especificada por el nmero entero contenido en el parmetro c. bcmod($a,$b)

devuelve el resto de la divisin entera de los valores contenidos en las cadenas $a y $b. bcpow($a,$b,c)

Devuelve el resultado de elevar el valor numrico contenido en la cadena $a a la potencia expresada por la cadena $b dando el resultado con la cantidad de decimales sealada por el parmetro c.

bcsqrt($a,c)

Devuelve la raz cuadrada del valor numrico contenido en la cadena $a con la cantidad de decimales sealada por el parmetro c. bccomp($a,$b,c)

Compara los valores contenidos en las cadenas $a y $b teniendo en cuenta nicamente el nmero de decimales especificados en c. Si $a>$b devuelve 1. Si las magnitudes comparadas son iguales devuelve 0 y si son distintas devuelve 1. Si comparamos $a='3.456' (es necesario indicar siempre los valores como cadenas) con $b='3.45' obtendremos como resultado: bccomp($a,$b,0)=0 bccomp($a,$b,1)=0 bccomp($a,$b,2)=0 bccomp($a,$b,3)=1 Compara 3 con 3 que obviamente son iguales Compara 34 con 34. Son iguales y por tanto devuelve cero Compara 345 con 345. Son iguales y por tanto devuelve cero Compara 3456 con 3450. No son iguales y por tanto devuelve uno

En el cuadro puedes ver, sealados en rojo, los resultados de efectuar la misma operacin utilizando el operador de coma flotante y estas funciones de precisin arbitraria. Si comparas las diferencias en los resultados obtenidos con cada una de ellas podrs darte idea del error provocado por los inevitables redondeos de la operacin con coma flotante.

Comparacin de punto flotante y precisin arbitraria


Comparacin de funciones matemticas
Operacin Variable Valor

$A S U M A $B bcadd($A,$B,0) $a=(double)$A $b=(double)$B

"12345678910123456789012345678901234567890" "45678910123456789012345678901234567890123" 58024589033580245801358024580135802458013 1.23456789101E+40 4.56789101235E+40

$a+$b $C $D bcadd($C,$D,50) $c=(double)$C $d=(double)$D $c+$d $A $B bcsub($A,$B,0) $a=(double)$A $b=(double)$B R E S T A $a-$b $C $D bcsub($C,$D,50) $c=(double)$C $d=(double)$D $c-$d $A $B bcmul($A,$B,0) $a=(double)$A P R O D U C T O $b=(double)$B $a*$b $C $D bcmul($C,$D,62) $c=(double)$C $d=(double)$D $c*$d $A D I V I S I N $B bcdiv($A,$B,30) $a=(double)$A $b=(double)$B $a/$b $C $D

5.80245890336E+40 58024589033580236333428572634998418440192 "0.0002345678902" "0.00000000000000000000000000000000000000001523786" 0.00023456789020000000000000000000000000001523786000 0.0002345678902 1.523786E-41 0.0002345678902 0,00023456789020000001029161995624860992393223568797 "12345678910123456789012345678901234567890" "45678910123456789012345678901234567890123" -33333231213333332223333333222333333322233 1.23456789101E+40 4.56789101235E+40 -3.33332312133E+40 -33333231213333327795815413198205132734464 "0.0002345678902" "0.00000000000000000000000000000000000000001523786" 0.00023456789019999999999999999999999999998476214000 0.0002345678902 1.523786E-41 0.0002345678902 0,00023456789020000001029161995624860992393223568797 "12345678910123456789012345678901234567890" "45678910123456789012345678901234567890123" 56393715734858534797546128354926080723008626986848 1383972550423718379870903950470 1.23456789101E+40 4.56789101235E+40 5.63937157349E+80 56393715734858529559076134525051001632068799181691 5078270593363632973621514731520 "0.0002345678902" "0.00000000000000000000000000000000000000001523786" 0.000000000000000000000000000000000000000000003574 312671362972 0.0002345678902 1.523786E-41 3.57431267136E-45 0 0,000000000000000000000000000000000000000000003574 31267136297184 "12345678910123456789012345678901234567890" "45678910123456789012345678901234567890123" 0.270270872854818178953756836882 1.23456789101E+40 4.56789101235E+40 0.270270872855 0,270270872854818211550309570157 "0.0002345678902" "0.00000000000000000000000000000000000000001523786"

bcdiv($C,$D,30) $c=(double)$C $d=(double)$D $c/$d $A R E S T O S $B bcmod($A,$B) $a=(double)$A $b=(double)$B $a % $b $A $B

15393755435474535138136194977509965310.08947450626 2690430283517501801 0.0002345678902 1.523786E-41 1.53937554355E+37 15393755435474538599292516471769399296,00000000000 0000000000000000000 "12345678910123456789012345678901234567890" "57" 19 1.23456789101E+40 57 0 "12345678910123456789012345678901234567890" "13" 15477282435120092620517640487873307882539433894477 02478876805675247359287360605519476488004915460644 30130253272627846453956411651820029120439549209342 64779279536097719586538292066102759581864670705845 47341619065960659102701030110334399943453939049941 81961179086427277645221130645386339095405377300948 55610257804029129290263282188925049521874093123594 94558994966581650612470024575134583192369561297975 69626211024080786875604177270092747586939296603680 65512433192215011092075340601280601173670507434702 7729224690000000000000 1.23456789101E+40 13 INF inf "12345678910123456789012345678901234567890" "13" 111111110651111110153.9111071478030905799220364 1.23456789101E+40 13 1.11111110651E+20 111111110651111112704,0000000000000000000000000

P O T E N C I A

bcpow($A,$B)

$a=(double)$A $b=(double)$B pow($a, $b) C U A D R A D A $A $B bcsqrt($A,15) $a=(double)$A $b=(double)$B Sqrt($a)

R A I Z

Aunque las diferencias de resultados puedan parecer muy grandes en valor absoluto (hemos exagerado premeditadamente los valores operados (tanto en valores grandes como en valores pequeos) los errores relativos son de escasa significacin. En la inmensa mayora de las situaciones (por no decir todas las cotidianas) resulta suficiente utilizar los operadores de coma flotante.

Logaritmos y trigonometra Logartmos y trigonometra


La sintaxis para el uso de las funciones logartmicas y trigonomtricas es esta: log($a)

Devuelve el valor del logaritmo neperiano de valor numrico contenido en la variable $a

Log10($a)

Devuelve el valor del logaritmo decimal de valor numrico contenido en la variable $a Exp($a)

Devuelve el valor del nmero e elevado a la variable $a (e ) Operaciones con logaritmos


Operacin Sintaxis log($a) log($a) Log10($a) Log10($a) Exp($a) Exp($a) Exp($a)
a a

$a

Resultado

Logaritmo neperiano Logaritmo neperiano Logaritmo decimal Logaritmo decimal exponencial e exponencial e exponencial e
a a a

12 -7.3 12 -7.3 12 1 -7.3 12 -7.3

2.48490664979 NAN 1.07918124605 NAN 162754.791419 2.71828182846 0.000675538775194 1000000000000 5.01187233627E-8

exponencial 10 exponencial 10

pow(10,$a) pow(10,$a)

Al realizar una operacin cuyo resultado no es un nmero real PHP devuelve la cadena NAN tal como puedes ver en los ejemplos delogaritmos de nmeros negativos. Las funciones trigonomtricas tanto las directas como las inversas consideran los valores de los angulos expresados en radianes. pi()

devuelve el valor del nmero irracional Sin($a)

devuelve el valor del seno del angulo $a expresado en radianes Cos($a)

devuelve el valor del coseno del angulo $a expresado en radianes Tan($a)

devuelve el valor de la tangente del angulo $a expresado en radianes deg2rad($a)

Transforma en radianes el del angulo $a expresado en grados sexagesimales Funciones trigonomtricas

Operacin

Sintaxis Pi() Sin($a) Sin(pi()) Cos($a) Cos(pi()) Tan($a) Tan(pi()) Tan(pi()) deg2rad($a) deg2rad($a)

Resultado

Valor de PI Seno de A (radianes) Seno de PI (radianes) Coseno de A (radianes) Coseno de PI (radianes) Tangente de A (radianes) Tangente de PI (radianes) Tangente de PI/2 (radianes) Pasa grados a radianes Pasa grados a radianes Asin($a)

3.14159265359 12 pi() 12 pi() 12 pi() pi()/2 45 30.8 -0.536572918 1.22464679915E-16 0.843853958732 -1 0.843853958732 -1.22464679915E-16 1.63312393532E+16 0.785398163397 0.537561409614

devuelve, expresado en radianes, la medida del angulo cuyo seno es $a Acos($a)

devuelve, expresado en radianes, la medida del angulo cuyo coseno es $a Atan($a)

devuelve, expresado en radianes, la medida del angulo cuya tangente es $a rad2deg($a)

convierte en grados sexagesimales la medida del angulo $a expresado en radianes Funciones trigonomtricas inversas
Operacin Sintaxis Asin($a) Asin($a) Acos($a) Acos($a) Atan($a) Atan($a) rad2deg($a) A Resultado

Arco seno de A (en radianes) Arco seno de A (en radianes) Arco coseno de A (en radianes) Arco coseno de A (en radianes) Arco tangente de A (en radianes) Arco tangente de A (en radianes) Pasa radianes a grados

0.8 12 0.8 12 0.8 12 pi()/4

0.927295218002 NAN 0.643501108793 NAN 0.674740942224 1.48765509491 45

Cambios de base y formatos Formatos de las variables numricas


En PHP, para asignar valores numricos a una variable pueden utilizarse uno de los siguientes sistemas de numeracin: Los nmeros enteros pueden escribirse en una cualquiera de estas bases: Base decimal $a=nmero

No se pueden insertar ceros a la izquierda cuando se escriben nmeros en base decimal. Base octal $a=0nmero octal Basta poner un CERO delante del nmero para que sea interpretado como escrito en base OCTAL. Obviamente, slo admite los dgitos de 0 a 7. Base hexadecimal $a=0xnmero hexadecimal Si se escribe CERO EQUIS (0x) delante del nmero, PHP lo interpretar como expresado en hexadecimal. En este caso, admitir como dgitos de 0 a 9 y de A a F. Un nmero de coma flotante puede escribirse de cualquiera de estas formas: Notacin decimal. $a=nmero Se puede utilizar un cero a la izquierda del punto decimal. Notacin cientfica $a=nmero e exponente Se puede utilizar un cero a la izquierda del punto decimal. Un ejemplo: $a=1.2e5 asigna a $a el valor: 1.2 x 10 . Cuando el -5 exponente es negativo $a=1.2e-5 asigna a $a el valor: 1.2 x 10 Asignacin de valores en distintas bases
Base Sintaxis $a=17 $a=017 $a=0x17 $a=0x1A3B $a=123000; $a=0.174 $a=1.23e5; $a=23.4e-2; Valor decimal Aplicable a
5

Base Decimal Base Octal Base Hexadecimal Base Hexadecimal Notacin decimal Base Decimal Notacin cientfica Notacin cientfica

17 15 23 6715 123000 0.174 123000 0.234

Nmeros enteros Nmeros enteros Nmeros enteros Nmeros enteros Coma flotante Coma flotante Coma flotante Coma flotante

Cambios de base
PHP permite hacer todo tipo de cambios de base. Para evitar ser reiterativos, observa los ejemplos. All tienes las diferentes funciones mediante las que se puede realizar ese proceso. Asignacin de valores en distintas bases
Valor de la variable Base Nueva base Sintaxis decoct($a) dechex($a) decbin($a) octdec($a) hexdec($a) Expresin

$a=1234 $a=1234 $a=1234 $a=1234 $a=1234

10 10 10 8 16

8 16 2 10 10

2322 4d2 10011010010 668 4660

$a=1010011 $a=1234 $a=1234 $a=1234

2 7 5 18

10 14 18 5

bindec($a) base_convert($a,7,14) base_convert($a,5,18) base_convert($a,18,5)

83 254 ae 202123

Presentaciones numricas
La presentacin de los valores numricos permite una gran variedad de formatos. El nmero de cifras decimales, los separadores de decimales y los separadores de mil pueden configurarse a voluntad utilizando alguna de estas funciones. number_format (nmero) Presenta la parte entera del nmero (sin decimales) y utiliza como separador de miles una coma (,). number_format (nmero , nmero de cifras decimales) Presenta el nmero de cifras decimales que se indiquen y utiliza como separador decimal un punto (.) y el separador de miles es una coma (,). number_format (nmero , nm decimales , "sep. decimal" , "sep. miles") Permite establecer el nmero de cifras decimales de la presentacin as como el carcter que se establezca como separador de decimales y como separadores de miles. Cuidado!. No te olvides de escribir los caracteres de separacin entre comillas. Formatos de presentacin de nmero
Valor inicial N de decimales Sep. dec. Sep. miles Sintaxis number_format($a) number_format($a,2) number_format($a ,2 , "," ,".") number_format($a ,2 , " ' " ," ") Resultado

$a=1234567.234 $a=1234567.234 $a=1234567.234 $a=1234567.234

0 2 1 1 . , '

, , . esp

1,234,567 1,234,567.23 1.234.567,2 1 234 567'2

Nmeros aleatorios El valor Unix Epoch


El conocido como tiempo UNIX o tambin Unix Epoch es un sistema referencia de tiempo cuya unidad son los segundos y que tiene su valor cero a las 00:00:00 horas (GMT) del da uno de enero de 1970. time()

La funcin time() devuelve el nmero de segundos transcurridos desde el comienzo de la Unix Epoch hasta el momento actual. Que cuantos son? Pues mira, desde el comienzo del tiempo UNIX hasta este mismo instante han transcurrido 1 338 997 370 segundos microtime()

Usando la funcin microtime() se obtiene una cadena que, adems del nmero de segundos transcurridos desde el comienzo de laUnix Epoch, incluye al comienzo de ella y separada por un espacio la parte decimal de ese tiempo expresada en microsegundos. El valor de la cadena devuelta por microtime() en este instante es 0.32155100 1338997370 . Como vers, aparece la fraccin decimal del tiempo Unix Epoch delante de su valor entero. (double)microtime()

Dado que microtime() devuelve una cadena, es posible convertirla en nmero de coma flotante anteponiendo (double) que, como recordars, es la funcin que permite forzar una cadena a nmero coma flotante. Una vez cambiado el tipo de variable el valor devuelto pormicrotime se convierte en: 0.321555 que como puedes observar es un nmero con seis decimales (si las ltimas cifras son ceros no se visualizarn). Si se multiplica el valor anterior por 1.000.000 obtenemos un nmero entero de seis cifras que cambia de valor cada millonsima de segundo. Observa el resultado de esta operacin: 321563 Fjate que ha cambiado! La diferencia no es otra cosa que el tiempo transcurrido entre los instantes en que se ejecutaron ambas instrucciones.

Nmeros aleatorios
PHP dispone de dos funciones capaces de generar nmeros aleatorios. Se trata de la funcin rand() y de la funcin mejoradamt_rand(). Generacin de un nmero aleatorio
Generador rand() Sintaxis echo rand() N aleatorio Generador mt_rand() Sintaxis echo mt_rand() N aleatorio

1691253796

1938204944

El nmero aleatorio generado est comprendido entre CERO y un valor mximo que puede determinarse para cada una de las dos opciones mediante las funciones getrandmax() y mt_getrandmax() Estos son sus valores. Valores mximos de los generadores de nmeros aleatorios
Generador rand() Sintaxis echo getrandmax() Valor mximo Generador mt_rand() Sintaxis echo mt_getrandmax() Valor mximo

2147483647

2147483647

Segn las libreras que est usando PHP, puede ocurrir que los valores mximos con ambos generadores sean iguales.

Una semilla que mejora la aleatoriedad


Se pueden ejecutar las funciones srand() o mt_srand() incluyendo en ellas una expresin como la especificada en rojo srand((double)microtime()*1000000) mt_rand((double)microtime()*1000000)

antes de invocar a las funciones rand() o mt_rand(). De esta forma estaremos introduciendo una semilla cuyo valor, tal como comentamos en el epgrafe anterior, se modifica cada millonsima de segungo y que mejora sustancialmente la aleatoriedad de los nmeros obtenidos. Aqu tenemos un ejemplo: Generacin de un nmero aleatorio con semilla
Generador rand() Sintaxis N aleatorio

srand((double)microtime()*1000000); echo rand() Generador mt_rand() Sintaxis mt_srand((double)microtime()*1000000); echo mt_rand()

82654550

N aleatorio 909959302

Manteniendo la sintaxis anterior no te olvides de incluir las semillitas se pueden generar nmeros aleatorios comprendidos dentro del intervalo que preestablezcamos. Bastara con aadir los valores de los extremos de ese intervalo como parmetros de la funcin. La sintaxis sera esta: rand(extremo inferior , extremo superior) y para la funcin mejorada mt_rand(extremo inferior , extremo superior) Generacin de un nmero aleatorio delimitando intervalos
Generador rand() Sintaxis srand((double)microtime()*1000000); echo rand(1,300) Generador mt_rand() Sintaxis mt_srand((double)microtime()*1000000); echo mt_rand(1,300) N aleatorio 173 N aleatorio 126

Variables tipo cadena Las variables de cadena


A las variables tipo cadena se les puede asignar los valores escribiendo el contenido entre comillas $var="Texto del contenido"; o por medio de la conocida como sintaxis de documento incrustado que es la siguiente: $var= <<< EOD ... contenido de la cadena... ... puede ir .... .. en varias lneas... EOD; donde EOD es una palabra cualquiera que debe repetirse exactamente igual al final de la instruccin. La sintaxis de documento inscrutado requiere tener presentes algunas consideraciones: El nombre de la variable, el signo igual que la precede, los tres smbolos < y el EOD deben escribirse en la misma lnea, que esta vez no ir acabada en punto y coma (observa que no acaba all la instruccin). Puede incluirse el texto (valor de la variable) en tantas lneas como se desee, pero hay que tener en cuenta que a la hora de visualizar el documento no se mantiene esa estructura ya que HTML slo entiende la etiqueta <BR> como indicador de salto de lnea. El cierre de la instruccin debe hacerse siempre escribiendo el EOD al comienzo una nueva lnea independiente que ahora s tiene que llevar el punto y coma que indica a PHP el final de una instruccin. Aqu tienes un ejemplo en el que se utilizan las dos formas de asignacin de valores a una cadena.

<html> <head>

<title>Ejemplo 34 - PHP</title> </head> <body> <?php $cadena1="Esto es una cadena de texto"; $cadena2= <<<Pepe Esta es otra cadena escrita con la sintaxis de documento incrustado. Se escribe en varias lneas y tiene la sintaxis siguiente. Despus de escribir el nombre de la variable y el signo igual se ponen los tres <<< y un nombre cualquiera. En este caso, Pepe. Luego hay que saltar de lnea y escribir el texto con las lneas que se desee, pero cuidado... a la hora de visualizar la cadena con la instruccin echo todo este texto se ver seguido ya que para que se visualizaran saltos de lnea en una pgina web habra que poner las famosas etiquetas <BR>. Se indica el final de la cadena escribiendo de nuevo el nombre asignado en la primera lnea -Pepe- pero teniendo la precaucin de escribirlo en una linea nueva al final de todo el texto... As como lo ves en el cdigo fuente. Pepe; $cadena3= <<<Pepa Esta es otra cadena con el nombre Pepa puedo escribir Pepa cuantas veces quiera porque el PHP no interpretar el final de documento incrustado hasta que no la escriba en una sola linea y seguida del punto y coma Pepa; echo $cadena1,"<br>"; echo $cadena2,"<br>"; echo $cadena3,"<br>"; ?> </body> </html>
ejemplo34.php

Operaciones con cadenas


La concatenacin de cadenas
Para concatenar (unir en una sola cadena) varias porciones de texto hemos venido utilizando en las instrucciones print y echo un punto (.). Este punto (.) es un elemento muy importante que, adems de la forma que hemos visto en las pginas anteriores, tiene los siguientes usos: Unir dos cadenas y recogerlas en una variable $a="cad1" . "cad2"; o $a= $b . $c podemos obtener una nueva variable formada por la unin dos trozos. Pero seguramente te preguntars qu ocurre si juntamos una variable cadena y una numrica? o qu ocurre si juntamos dos variables numricas?

En cualquiera de los supuestos puedes verlo en el ejemplo las variables sern tratadas por PHP con independencia de lo que puedan contener como de tipo cadena y la variable que contiene el resultado es del tipo string. Aadir contenidos a una variable tipo string $a .="cad1" o $a .=$b Si utilizamos una sintaxis como esta (presta mucha atencin al punto que va delante del signo igual) se aadira al valor actual de la variable $a el contenido indicado despus del signo igual. Fjate en la importancia del punto. Si est presente se aaden nuevos contenidos a la variable. En el caso de que no estuviera se asignara a la variable nicamente lo incluido despus del signo igual. Aqu tienes un ejemplo de concatenacin de variables tipo string.

<?php #definamos y asignemos valores a variables tipo cadena $cadena1="Esto es una cadena de texto"; $cadena2="Esta es una segunda cadena de texto"; #hagamos lo mismo con variables numricas $cadena3=127; $cadena4=257.89; # unmoslas mezclando tipos $union1=$cadena1 . $cadena2; $union2=$cadena1 . $cadena3; $union3=$cadena3 . $cadena4; #veamos que ha ocurrido echo $union1,"<br>"; echo $union2,"<br>"; echo $union3,"<br>"; # modifiquemos ahora una cadena # aadiendole contenidos $cadena3 .=" Este es el texto que se aadir a la variable cadena3"; # imprimamos los resultados echo $cadena3,"<br>"; # aadamos ahora un nuevo trozo, esta vez # a partir de una cadena escrita con la # sintaxis de documento incrustado $cadena3 .= <<<Pepito Ahora le aado a la cadena este trocillo asignado con el "formato" de documento incrustado Pepito; # visualicemos el resultado echo $cadena3,"<br>"; ?>
ejemplo35.php

Cuidado! Observa en el ejemplo que, excepcionalmente, la sintaxis de documento incrustado permite introducir comillas (sin ningn mtodo especial), pero recuerda que en cualquier otro caso hay que recurrir al truco del que hablbamos en aqu.

Array escalar y asociativo Qu es un array?


Un array es algo tan simple una tabla de valores. Cada uno de los elementos de esa tabla se identifica por medio de un nombre(comn para todos) y un ndice (que sera el elemento diferenciador de cada uno de ellos). Mediante el uso de arrays podemos utilizar el mismo nombre para varias variables diferencindolas por medio de sus ndices. La sintaxis que permite definir elementos en un array es esta: $nombre[indice] dnde $nombre utiliza exactamente la misma sintaxis empleada para definir variables, con la nica particularidad de que ahora deben aadrsele los corchetes y los ndices. El ndice puede ser un nmero (habra que escribirlo dentro del corchete sin comillas), una cadena(que habra que poner en el corchete encerrada entre comillas sencillas '), o una variable que tampoco necesitara ir entre comillas. Cuando los ndices de un array son nmeros se dice que es escalar mientras que si fueran cadenas se le llamara array asociativo. Tablas unidimensionales
Array escalar Variable Indice Valor Array asociativo Variable Indice Valor

$a[0] $a[1] $a[2] $a[3] $a[4] $a[5] $a[6]

0 1 2 3 4 5 6

Domingo Lunes Martes Mircoles Jueves Viernes Sbado

$a['Primero'] $a['Segundo'] $a['Tercero'] $a['Cuarto'] $a['Quinto'] $a['Sexto'] $a['Septimo']

Primero Segundo Tercero Cuarto Quinto Sexto Septimo

Domingo Lunes Martes Mircoles Jueves Viernes Sbado

Arrays escalares
Los elementos de un array escalar puede escribirse con una de estas sintaxis: $a[]=valor $a[xx]=valor $a=array(valor0, valor1, valor2,...)

En el primero de los casos PHP asigna los ndices de forma automtica atribuyendo a cada elemento el valor entero siguiente al ltimo asignado. Si es el primero que se define le pondr ndice 0 (CERO). En el segundo de los casos, seremos nosotros quienes pongamos (xx) el nmero correspondiente al valor del ndice. Si ya existiera un elemento con ese ndice, se cambiara el valor de su contenido, en caso contrario crear un nuevo elemento del array y se le asignara como valor lo especificado detrs del signo igual que de la misma forma que ocurra con las variables debera ir entre comillas si fuera una cadena o sin ellas si se tratara de un nmero. En el tercero de los supuestos, la palabra array que precede al parntesis indica que cada uno de los valores numricos o cadenas separados por comas e incluidos dentro del parntesis son los valores correspondientes a los elementos de ndices 0, 1, 2... de un array escalar.

Arrays asociativos

Los elementos de un array asociativo (aquel cuyos ndices no son nmeros) pueden escribirse usando la siguiente sintaxis: $a['indice']=valor

En este caso estamos obligados a escribir el nombre del ndice que habr de ser una cadena escrita entre comillas o tambin una variable definida previamente y con ese tipo de contenido. Tanto en el caso de los array asociativos como en los escalares es posible y bastante frecuente utilizar como ndice el contenido de una variable. El modo de hacerlo sera este $a[$indice]=valor

En este caso, sea cual fuere el valor de la variable $indice, el nombre de la variable nunca se pone entre comillas.

Ejemplo de arrays unidimensionales


<?php # Crearemos un array escalar (basta con definir un elemento) $a[2]="Este elemento es el segundo del array"; # creemos un nuevo elemento de ese array # esta vez de forma automtica # si ponemos corchetes vacos va aadiendo ndices automaticamente $a[]="Ser este tercero?"; # comprobemos que le ha puesto ndice 3 echo "El elemento ".$a[3]." tiene indice 3 (siguiente a 2) <br>"; # ahora insertemos un nuevo elemento con indice 32 $a[32]="Mi indice es 32"; # insertemos otro elemento de forma automtica $a[]= "Ir a parar al indice 33 este elemento?"; # la insercin se har con indice 33, comprobmoslo print "Vemos que contiene el elemento de indice 33 ...".$a[33]."<br>"; # qu ocurrir si pido que imprima el elemento 21 que nadie ha definido # seguramente estar vacio, comprobmoslo!! # antepondremos el @ para evitar el mensaje de advertencia de PHP @print ("Aqui--> ". $a[21]. "<--- si es que hay algo<br>"); # ahora crearemos un nuevo array llamado $b # insertmosle de forma automatica su PRIMER elemento $b[]="Estoy empezando con el array b y mi indice ser cero"; # comprobemos que efectivamente ha empezado con indice CERO print ($b[0]."<br>"); # veamos ahora eso de los arrays asociativos # creemos uno llamado $c con varios elementos $c["objeto"]="coche"; $c["color"]="rojo"; $c["tamao"]="ideal"; $c["marca"]= "Ferrari"; $c["precio"]="prohibitivo para un humilde docente"; #encadenemos variables para hacer una salida # pondremos cadenas " " para que no aparezcan los textos # pegados unos a otros.. $salida="<H2> El ". $c["objeto"] ." ".$c["marca"]." ".$c["color"]; $salida .=" tiene el tamao ideal ".$c["tamao"]; $salida .=" y su precio es ".$c["precio"]; $salida .="</H2>"; print $salida; # sigamos experimentando ahora # qu ocurrira si nos olvidamos de poner nombre al indice # e insertamos un corchete vacio lo creara?que indice pondria? # probemos ....

$c[]="crear un array escalar nuevo y le pondr indice cero?"; # tratemos ahora de visualizar esa variable # probemos a escribir $c[0] porque PHP # habr entendido que queremos un array escalar # y como no existe ninguno con ese nombre empezar por cero # comprobmoslo echo $c[0]; ?>
ejemplo36.php

Arrays bidimensionales Arrays bidimensionales


Los arrays bidimensionales pueden entenderse como algo bastante similar a una tabla de doble entrada. Cada uno de los elementos se identifica sigue siendo vlido el nombre nico que se usaba en los unidimensionales por un nombre ($nombre) seguido de dos ([ ]) que contienen los ndices (en este caso son dos ndices) del array. Los ndices pueden ser de tipo escalar -equivalen al nmero de fila y columna que la celda ocupa en la tabla asociativos lo que equivaldra en alguna medida a usar como ndices los nombres de la fila y de la columna y tambin mixtos (uno de los ndices es escalar y el otro asociativo).

Cuidado!
No dejes de tener en cuenta lo que hemos advertido al hablar de arrays unidimensionales. En este supuesto, tambin, se empiezan a numerar los arrays escalares a partir de CERO.

Arrays bidimensionales escalares


Los elementos de un array bidimensional escalar pueden escribirse usando una de estas sintaxis: $a[ ][ ]=valor o $a[xx][ ]=valor o $a[ ][xx]=valor o tambin $a[xx][yy]=valor

En el primero de los casos PHP asigna automticamente como primer ndice el valor que sigue al ltimo de los asignado a ese mismo ndice y, si es el primero que se define, le pondr como ndice 0 (CERO). Sea cual fuere el valor de primer ndice al segundo se le asignar cero ya que es en este mismo momento cuando se habr creado el primero y, por tanto, an carecer de elementos. En el segundo de los casos, asignamos un valor al primer ndice (xx) y ser el segundo quien se incremente en una unidad respecto al de valor ms alto de todos aquellos cuyo primer ndice coincide con el especificado. La tercera opcin es bastante similar a la anterior. Ahora se modificara automticamente el primer ndice y se escribira el contenido (xx) como valor del segundo. En la cuarta de las opciones se asignan libremente cada uno de los ndices (xx e yy) ponindoles valores numricos. Este es un ejemplo de uso de array bidimensionales escalares.

<?php # rellenamos el array desde [0][0] hasta [0][4] # la insercion automatica haria que este primero fuera [0][0] $a[][]=" ";

# ahora pondremos cero como indice del primer array y dejemos que PHP # nos vaya insertando automaticamente el segundo $a[0][]="3-2";$a[0][]="5-3";$a[0][]="7-1";$a[0][]="0-2"; #ahora desde [1][0] hasta [1][4] #este primero lo dejamos como automtico en ambos indices # de esta forma el primero tomar valor uno (siguiente al anterior) # de forma automtica $a[][]="0-11"; # repetimos el proceso anterior $a[1][]=" ";$a[1][]="2-1";$a[1][]="1-0";$a[1][]="1-2"; # y repetimos de nuevo, ahora crearia 2 como primer indice $a[][]="0-0"; #insertariamos los restantes valores de indice 2 $a[2][]="1-3";$a[2][]=" ";$a[2][]="1-4";$a[2][]="2-0"; # nuevo incremento del primer indice $a[][]="1-0"; # rellenamos $a[3][]="6-3";$a[3][]="14-3 ";$a[3][]=" ";$a[3][]="1-0"; # nuevo y ultimo incremento de primer indice $a[][]="1-1"; # rellenamos de nuevo $a[4][]="2-3";$a[4][]="0-1 ";$a[4][]="1-1";$a[4][]=""; # como vers el proceso no tiene complicaciones, pero ... pesadillo si es # verdad que si tuviramos una base de datos sera ms fcil? # estamos en ello, todo se andar... # # # # # tendramos que ver esos valores pero.. escribir "a mano" una tabla puede ser una tortura, as que mejor introducimos una bucle, otro recurso que estudiaremos pronto para esa labor repetitiva de mostrar en una tabla todos los datos del array

# Sera algo como esto # creamos la etiqueta de apertura de una tabla print ("<TABLE BORDER=2>"); # ahora dos bucles anidados (rojo uno, magenta el otro) # para rellenar las celdas de cada fila (el magenta) # y para insertar las etiquetas <TR> utilizaremos el rojo # antepondremos el @ a print para evitar mensaje de error for ($i=0;$i<5;$i++){ print("<tr>"); for($j=0;$j<5;$j++) { @print("<td>".$a[$i][$j]."</td>"); } } #ponemos la etiqueta de cierre de la tabla print("</table>"); ?>
ejemplo37.php

Utilizando el script anterior, con ligeros retoques estticos, hemos construido esta tabla:

Todos los resultados de la liguilla


Indice 0

2 2-1

0 1 2 3 4 0-11 0-0 1-0 1-1

3-2 5-3 1-3 6-3 14-3 2-3 0-1

7-1 0-2 1-0 1-2 1-4 2-0 1-0 1-1

Arrays bidimensionales asociativos


Los elementos de un array asociativo bidimiensional se pueden escribir usando la siguiente sintaxis: $a["indice1"]["indice2"]=valor

En este caso, los ndices sern cadenas y se escribirn entre comillas. Como ejemplo de array bidimensional emplearemos una tabla de resultados de una liga de ftbol en la que intervienen cinco equiposque como en toda liga que se precie se juega a doble partido. Resultados de la liguilla
Indice

Juvencia Mosconia Canicas Condal Piloesa 3-2 0-0 1-0 1-3 6-3 2-3 14-3 0-1 1-1 5-3 2-1 7-1 1-0 1-4 0-2 1-2 2-0 1-0

Juvencia Mosconia 0-11 Canicas Condal

Piloesa 1-1

Arrays multidimensionales Arrays multidimensionales


PHP permite el uso de arrays con dimensin superior a dos. Para modificar la dimensin del array basta con ir aadiendo nuevos ndices. $a[x][y][z]=valor; asignara un valor al elemento de ndices x, y y z de un array tridimensional $a[x][y][z][w]=valor; hara lo mismo, ahora con un array de dimensin cuatro. Pueden tener cualquier tipo de ndices: escalares, asociativos y, tambin, mixtos.

La funcin array();
Para asignar valores a una matriz puede usarse la funcin array(), que tiene la siguiente sintaxis:

$a= array ( ndice 0 => valor, ..... , ndice n => valor, ); Por ejemplo: $z=array (0 =>2, 1=>"Pepe", 2=>34.7, 3=>"34Ambrosio") producir igual resultado que: $z[0]=2; $z[1]="Pepe"; $z[2]=34.7; $z[3]="34Ambrosio"

Anidando en array();
La funcin array() permite escribir arrays de cualquier dimensin utilizando la tcnica de anidado. Si pretendemos escribir los elementos de este array: $z[0][0]=34; $z[0][1]=35; $z[0][2]=36; $z[1][0]=134; $z[1][1]=135; $z[1][2]=136; podriamos hacerlo asi:

$z=array( 0 => array ( 0 => 34, 1 => 35, 2 => 36, ), 1 => array ( 0 => 134, 1 => 135, 2 => 136, ) );
Como puedes observar, se trata de sustituir los valores asignados a los elementos de una primera funcin array() por otra nueva funcin array que contiene los segundos ndices asi como los valores asignados a los mismos. El anidado sucesivo permitira generar arrays de cualquier dimensin. Aunque en el ejemplo anterior nos hemos referido a un array escalar, idntico procedimiento sera vlido para arrays asociativos con slo cambiar los nmeros por cadenas escritas entre comillas. Este podra ser un ejemplo de array asociativo: $z['a']['A']=34; $z['a']['B']=35; $z['a']['C']=36; $z['b']['A']=134; $z['b']['B']=135; $z['b']['C']=136; que podra definirse tambin de esta forma:

$z=array( "a" => array ( "A" => 34, "B" => 35, "C" => 36, ), "b" => array ( "A" => 134, "B" => 135, "C" => 136, ) );

A medida que la dimensin se hace mayor la sintaxis requiere muchsima ms atencin y los errores son poco menos que inevitables. Refresquemos un poco la memoria. No olvides los punto y coma del final de las instrucciones. Cuidado con las formas anidadas y tambin con los parntesis. Cierra cada uno de los parntesis que abras y no olvides que los parntesis se anidan, ya sabes... el primero que se abre siempre con el ltimo que se cierra, el segundo con el penltimo, etctera. No dejes de prestar atencin a las comillas. Recuerda que hay que cerrarlas siempre y que hay que diferenciarlas en los casos en que van comillas dentro de otras comillas. Esta es la forma en la que hemos definido el array tridimensional que utilizaremos en el ejemplo.

<?php $b = array( "Juvencia" => array( "Juvencia" => array ( "Resultado" => " ", "Amarillas" => " ", "Rojas" => " ", "Penalty" => " " ), "Mosconia" => array ( "Resultado" => "3-2", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "1" ), "Canicas" => array ( "Resultado" => "5-3", "Amarillas" => "0", "Rojas" => "1", "Penalty" => "2" ), "Condal" => array ( "Resultado" => "7-1", "Amarillas" => "5", "Rojas" => "2", "Penalty" => "1" ), "Piloesa" => array ( "Resultado" => "0-2", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), ), "Mosconia" => array( "Juvencia" => array ( "Resultado" => "0-11 ", "Amarillas" => "4", "Rojas" => "2", "Penalty" => "4" ), "Mosconia" => array ( "Resultado" => " ", "Amarillas" => " ", "Rojas" => " ", "Penalty" => " " ),

"Canicas" => array ( "Resultado" => "2-1", "Amarillas" => "0", "Rojas" => "0", "Penalty" => "2" ), "Condal" => array ( "Resultado" => "1-0", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), "Piloesa" => array ( "Resultado" => "1-2", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), "Canicas" ), => array( "Juvencia" => array ( "Resultado" => "0-0", "Amarillas" => "0", "Rojas" => "1", "Penalty" => "1" ), "Mosconia" => array ( "Resultado" => "1-3", "Amarillas" => "2", "Rojas" => "0", "Penalty" => "1" ), "Canicas" => array ( "Resultado" => " ", "Amarillas" => " ", "Rojas" => " ", "Penalty" => " " ), "Condal" => array ( "Resultado" => "1-4", "Amarillas" => "2", "Rojas" => "1", "Penalty" => "1" ), "Piloesa" => array ( "Resultado" => "2-0", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), ), => array( "Juvencia" => array ( "Resultado" => "1-0 ", "Amarillas" => "4", "Rojas" => "1", "Penalty" => "2" ), "Mosconia" => array ( "Resultado" => "6-3", "Amarillas" => "1", "Rojas" => "2",

"Condal"

"Penalty" => "3" ), "Canicas" => array ( "Resultado" => "14-3", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), "Condal" => array ( "Resultado" => " ", "Amarillas" => " ", "Rojas" => " ", "Penalty" => " " ), "Piloesa" => array ( "Resultado" => "1-0", "Amarillas" => "3", "Rojas" => "1", "Penalty" => "0" ), "Piloesa" ), => array( "Juvencia" => array ( "Resultado" => "1-1", "Amarillas" => "0", "Rojas" => "0", "Penalty" => "1" ), "Mosconia" => array ( "Resultado" => "2-3", "Amarillas" => "1", "Rojas" => "0", "Penalty" => "0" ), "Canicas" => array ( "Resultado" => "0-1", "Amarillas" => "0", "Rojas" => "0", "Penalty" => "0" ), "Condal" => array ( "Resultado" => "1-1", "Amarillas" => "1", "Rojas" => "2", "Penalty" => "0" ), "Piloesa" => array ( "Resultado" => " ", "Amarillas" => " ", "Rojas" => " ", "Penalty" => " " ), )

); ?>
ejemplo38.php

Presentacin de nmeros Funciones de salida


Ya conocemos algunas de las funciones que PHP utiliza para mostrar informacin salidas en la ventana del navegador del cliente. Recordmoslas: echo

La funcin echo, aunque admite tambin la forma echo(), no requiere de forma obligatoria el uso de los parntesis. Detrs de lainstruccin echo pueden insertarse: variables, cadenas (stas entre comillas) y nmeros (stos sin comillas) separadas por comas. Este es un ejemplo de cdigo: $a=24; $b="Pepe"; $c="<br>"; echo $a,$b,25, "Luis",$c; que producira esta salida: 24Pepe25Luis print()

La funcin print() slo puede contener dentro del parntesis una sola variable, o el conjunto de varias de ellas enlazadas por un punto. Aqu tienes algunos ejemplos: print(25.3) producira esta salida 25.3 print("Gonzalo") escribira Gonzalo $z=3.1416; print($z); escribira 3.1416 Recuerda tambin que es posible utilizar dentro del parntesis el concatenador de cadenas. $h=3; $f=" hermanos"; print("Heladeria ".$h.$f) que escribira Heladeria 3 hermanos

Salidas con formato


Ni la funcin echo, ni tampoco print permiten establecer una presentacin (formato) en sus salidas, excepto que alguna de las variables que se use contenga el resultado de una funcin number_format. La funcin printf() ofrece un gran nmero de posibilidades en este sentido. Tanto la sintaxis como los valores de los diferentes parmetros cuando se trate de presentar nmeros las tienes resumidas en la tabla. En la pgina siguiente veremos el uso de printf() para el tratamiento de variables tipo cadena. Sintaxis printf(cadena de formato,variable1,variable2,..) Cadena de formato "%[relleno][alineacin][ancho][precisin][tipo]"
Carcter Valor

0 * 1) espacio Relleno

0 '* ' '-

Sintaxis printf("%020d",32) printf("%'*20d",32) printf("%' 20d",32) printf("%'-20d",32)

Resultado 00000000000000000032 ******************32 32 ------------------32

Observaciones En este apartado prestaremos atencin nicamente a los caracteres marcados en rojo, que son los que corresponden a las diferentes formas de relleno. Los dems parmetros los iremos tratando uno en los apartados siguientes. Cuando se pretende rellenar con ceros a la izquierda basta escribir el 0 inmediatamente detrs del

signo % Si se trata de rellenar con un carcter distinto de cero debe escribirse inmediatamente despus de% una comilla simple ' seguida del carcter de relleno. Si se pretende rellenar con espacios forzados se puede escribir la comilla simple 'einmediatamente despus teclear la combinacin ALT+0160 (carcter ASCII 160) usando el teclado numrico. Aunque obviamente no se visualiza el espacio si se conserva tal como puede verse en el ejemplo 1) Obsrvese que como la tipografa es de ancho variable y que segn el carcter que se use como relleno se modifica el ancho de la presentacin. Quiz convenga recordar que 32 es en este caso la variable a la que pretendemos dar formato y que ese valor podra ser sustituido por el nombre de una variable que contenga valores numricos. Carcter Ninguno Valor Dcha Izda Dcha Izda Dcha Izda Dcha Izda Sintaxis printf("%020d",32) printf("%020d",32) printf("%'*20d",32) printf("%'*20d",32) printf("%020s",32) printf("%020s",32) printf("%'*20s",32) printf("%'*20s",32) Resultado 00000000000000000032 32 ******************32 32****************** 00000000000000000032 32000000000000000000 ******************32 32******************

Ninguno Ninguno

Ninguno Observaciones

Alineacin En los casos en que figura Ninguno en la columna Caracter tratamos de indicar que no es
necesario escribir nada en la cadena de formato. Cuando aparece un signo () estamos indicando que debe insertarse un signo menos. Fjate que en los cuatro primeros supuestos el identificador de tipo es d, lo cual hace que considere la variable como numrica, mientras que en los cuatro ltimos ese valor es s, con lo cual considera la variable como tipo cadena. Cuando tratamos de rellenar una variable numrica con ceros por la derecha PHP los omite para no alterar el valor numrico en la presentacin Con cualquier otro carcter de relleno (incluidos los caracteres numricos con ' delante) s efecta el relleno. Carcter Entero Entero Decimal Decimal Decimal Decimal Valor 14 17 14.5 17.8 14.5 11.8 Sintaxis printf("%'*14d",32) printf("%'*-17d",32) printf("%'*14.5d",32) printf("%'*-17.8d",32) printf("%'*14.5f",32) printf("%'*-11.8f",32) Resultado ************32 32*************** ************32 32*************** ******32.00000 32.00000000

Ancho

Observaciones El ancho (n de caracteres totales) puede especificarse mediante un nmero entero para todo tipo de variables Si se expresa mediante un nmero decimal y la variable es tipo coma flotante la parte decimal indica la precisin (n de cifras decimales) y la parte entera el ancho como nmero de caracteres de la parte entera o de la parte decimal, segn se rellene a la derecha o a la izquierda. Tipo Presentacin en forma binaria Caracter correspondiente al cdigo ASCII Nmero presentado como entero Nmero presentado con decimales Presentacin en forma octal Presentacin en hexadecimal Presentacin en hexadecimal Presentacin como >cadena Valor b c Sintaxis printf("%'*14b",17) printf("%'*14c",97) Resultado *********10001 a

printf("%'*14d",17.83)

************17

Tipo

f o x X s

printf("%'*14f",17.45) printf("%'*14o",17) printf("%'*14x",170) printf("%'*14X",170) printf("%'*14s",170)

*****17.450000 ************21 ************aa ************AA ***********170

Cadenas alfanumricas (I) Funciones sobre cadenas


Algunas de las funciones que permiten manejar los formatos de las cadenas de caracteres son estas: chr(n)

Devuelve el carcter cuyo cdigo ASCII es n. ord(cadena)

Devuelve el cdigo ASCII del primero de los caracteres de la cadena. strlen(cadena)

Devuelve la longitud (nmero de caracteres) de la cadena. Los espacios son considerados como un caracter ms. strtolower(cadena)

Cambia todos los caracteres de la cadena a minsculas. strtoupper(cadena)

Convierte en maysculas todos los caracteres de la cadena. ucwords(cadena)

Convierte a maysculas la primera letra de cada una de las palabras de la cadena. ucfirst(cadena)

Convierte a maysculas la primera letra de la cadena y pone en minsculas todas las dems. ltrim(cadena)

Elimina todos los espacios que pudiera haber al principio de la cadena. rtrim(cadena)

Elimina todos los espacios que existieran al final de la cadena. trim(cadena)

Elimina los espacios tanto al principio como al final de la cadena.

chop(cadena)

Elimina los espacios al final de la cadena. Es idntica a rtrim.

Cuidado! Tanto trim, como ltrim y rtrim eliminan, adems de los espacios, las secuencias: \n, \r, \t, \v y \0; llamadas tambincaracteres protegidos.
substr(cadena,n)

Si el valor de n es positivo extrae todos los caracteres de la cadena a partir del que ocupa la posicin ensima a contar desde la izquierda. Si el valor de n es negativo sern extrados los n ltimos caracteres contenidos en la cadena. substr(cadena,n,m)

Si n y m son positivos extrae m caracteres a partir del que ocupa la posicin ensima, de izquierda a derecha. Si n es negativo y m es positivo extrae m (contados de izquierda a derecha) a partir del que ocupa la posicin ensima contada de derecha a izquierda. Si n es positivo y m es negativo extrae la cadena comprendida entre el ensimo carcter (contados de izquierda a derecha) hasta elemsimo, contando en este caso de derecha a izquierda Si n es negativo y m tambin es negativo extrae la porcin de cadena comprendida entre el emsimo y el ensimo caracteres contando, en ambos casos, de derecha a izquierda. Si el valor absoluto de n es menor que el de m devuelve una cadena vaca. strrev(cadena)

Devuelve la cadena invertida str_repeat(cadena, n)

Devuelve la cadena repetida tantas veces como indica n. str_pad(cadena, n, relleno, tipo)

Aade a la cadena los caracteres especificados en relleno (uno o varios, escritos entre comillas) hasta que alcance la longitud que indica n (un nmero) El parmetro tipo puede tomar uno de estos tres valores (sin comillas): STR_PAD_BOTH (rellena por ambos lados) STR_PAD_RIGHT(rellena por la derecha) STR_PAD_LEFT (rellena por la izquierda). Si se omite la cadena de relleno utilizar espacios y si se omite el tipo rellenar por la derecha str_replace(busca, sustituto, cadena)

Busca en la cadena las subcadenas de texto cuyo contenido es igual a busca, las reemplaza por el valor sustituto

substr_replace(cadena, sustituto, comienzo, longitud)

Sustituye por sustituto un nmero de caracteres igual a longitud contados a partir del que ocupa la posicin comienzo dentro de lacadena original. Cuando el valor de comienzo es negativo contar de derecha a izquierda para determinar el lugar de comienzo de la sustitucin. Si el valor de longitud es negativo no sustituir al final de la cadena un nmero de carcteres igual al valor absoluto de longitud. Estos son algunos ejemplos de aplicacin de las funciones de manejo de cadenas Cdigo ASCII y viceversa
Funcin chr(cdigo ASCII) ord("cadena") Ejemplo chr(97) ord("abadesa") Resultado a 97

Longitudes y conversiones maysculas/minsculas


Funcin strlen("cadena") strtolower("cadena") strtoupper("cadena") ucwords("cadena") ucfirst("cadena") Ejemplo strlen("Mide la longitud de esta cadena") strtolower("CONVIERTE A MINSCULAS") strtoupper("pasa a maysculas") ucwords("todas empiezan por mayscula") ucfirst("mayscula al principio") Resultado 31 convierte a minsculas PASA A MAYSCULAS Todas Empiezan Por Mayscula Mayscula al principio

Eliminar espacios
Funcin ltrim("cadena") rtrim("cadena") trim("cadena") chop("cadena") Ejemplo ltrim("\n \nEliminar espacios") rtrim("Eliminar espacios\n \n") trim("\n \nEliminar espacios\n \n") chop("\n \nEliminar espacios\n \n") Resultado Eliminar espacios Eliminar espacios Eliminar espacios Eliminar espacios

Extraer porciones de una cadena


Funcin substr("cadena",n) substr("cadena",n) substr("cadena",n) substr("cadena",n) substr("cadena",n,m) substr("cadena",n,m) substr("cadena",n,m) substr("cadena",n,m) substr("cadena",n,m) substr("cadena",n,m) Ejemplo substr("Extrae caracteres",3) substr("Extrae caracteres",0) substr("Extrae caracteres",-5) substr("Extrae caracteres",-2) substr("Extrae caracteres",2,6) substr("Extrae caracteres",0,8) substr("Extrae caracteres",2,-3) substr("Extrae caracteres",-7,5) substr("Extrae caracteres",-7,-5) substr("Extrae caracteres",-5,-7) Resultado rae caracteres Extrae caracteres teres es trae c Extrae c trae caracte acter ac

Modificaciones de cadenas
Funcin strrev("cadena") str_repeat("cadena",n) str_pad("cadena",n,"Relleno",Tipo) str_pad("cadena",n,"Relleno",Tipo) str_pad("cadena",n,"Relleno",Tipo) str_pad("cadena",n,"Relleno",Tipo) str_replace ("lo que dice",lo que dira,"Cadena") str_replace ("lo que dice",lo que dira,"Cadena") str_replace ("lo que dice",lo que dira,"Cadena") substr_replace ("Cadena",lo que dira,n,m) substr_replace ("Cadena",lo que dira,n,m) substr_replace ("Cadena",lo que dira,n,m) substr_replace ("Cadena",lo que dira,n,m) Ejemplo strrev("Invierte la cadena") str_repeat("Rep",5) str_pad("Pepe",10,"*",STR_PAD_BOTH) str_pad("Pepe",10,"*",STR_PAD_LEFT) str_pad("Pepe",10,"*",STR_PAD_RIGHT) str_pad("Pepe",10,"*") str_replace("e","a","Pepe") str_replace("pe","pa","Pepepe") str_replace("Pepe","Luis","Pepe") substr_replace("Esta es una cadena es de prueba","*",5,2) substr_replace("Esta es una cadena es de prueba","*",5,-2) substr_replace("Esta es una cadena es de prueba","*",-5,2) substr_replace("Esta es una cadena es de prueba","*",-5,-2) Resultado anedac al etreivnI RepRepRepRepRep ***Pepe*** ******Pepe Pepe****** Pepe****** Papa Pepapa Luis Esta * una cadena es de prueba Esta *ba Esta es una cadena es de p*eba Esta es una cadena es de p*ba

Formatos en cadenas
La funcion prinf tiene un comportamiento idntico al comentado en la pgina anterior.

printf(cadena de formato,variable1,variable2,..) Cadena de formato


Dentro de la cadena de formatos deben repetirse tantos formatos como variables se pretenda manejar "%[rell1][alin1][anc1][prec1][tipo1][sepa1]%[rell1][alin1][anc1][prec1][tipo1][sepa1]"

Hemos de mencionar aqu los separadores ya que no fueron mencionados en la pgina anterior Se puede introducir una cadena de separacin al final de una cadena de formato que puede hacer, entre otras, funcin de separacin entre dos cadenas. Por ejemplo, printf("%'*15.2f Euros",1475.875) nos devolvera: ********1475.88 Euros La funcin printf() permite presentar varios valores o variables con distintos formatos utilizando la sintaxis que se indica ms arriba. Este ejemplo : printf("%'*15.2f Euros=%'*18.0f Pesetas",1475.875,1475.875*166.386) devuelve como resultado: ********1475.88 Euros=************245565 Pesetas

Existe otra funcin PHP con caractersticas muy similares a la anterior. Se trata de sprintf(). La sintaxis es idntica sprintf (cadena de formato, variable1,variable2, ...) y su nica diferencia con printf es que, mientras que printf()imprime las variables utilizando el formato indicado, sprintf() puede guardar en una nueva variable la cadena resultante de la aplicacin del formato.

Cadenas alfanumricas (II) Funciones sobre cadenas


Como complemento a las descritas en la pgina anterior, aadimos aqu algunas otras funciones PHP que tambin permiten manejarcadenas de caracteres. AddSlashes(cadena) Inserta el carcter \ delante los siguientes: "(comillas dobles), ' (comillas simples), \ (escape) y NUL (el bit nulo). stripslashes(cadena) Quita las marcas aadidas a una cadena con la funcin AddSlashes().

chunk_split(cadena, n caracteres, separador ) Devuelve la cadena cadena despus de haberle insertado, cada n caracteres, la cadena indicada en el parmetro separador. Si no se indica separador PHP pondr un espacio. Si no se establece el parmetro n caracteres insertar el separador cada 76 caracteres. Esta funcin coloca siempre un separador al final de la cadena. parse_str(cadena) Devuelve las variables con su valor indicadas dentro de la cadena (observa la sintaxis del ejemplo). Dentro de la cadena cada variable se denomina con un nombre que va seguido de un signo igual. Los espacios se sealan con el signo + y los separadores de variables son signos & explode(separador, cadena,numero) Devuelve un array cuyos elementos contienen cada una de las porciones de la cadena (cadena) comprendidas entre dos de los caracteres sealados como (separador) hasta el mximo de porciones sealadas (numero). Los caracteres separadores no son includos en las cadenas resultantes. Si no se indica la cantidad de porciones, ser fraccionada toda la cadena. Si se indica numero el ltimo trozocontendr toda la cadena restante. implode(separador, array) Devuelve una cadena formada por todos los elementos del array separados mediante los caracteres indicados en separador. join(separador, array) Es idntica a implode. strtok(cadena, separador) Esta funcin divide la cadena cadena en trozos delimitados por el separador que se indica en separador. Cuando se invoca la primera vez extrae el primer trozo debe llevar las sintaxis strtok(cadena,separador). Al invocarla sucesivamente, se escribe solo strtok(" ") e ir recogiendo de forma secuencial los trozos sucesivos. Marcas, divisiones y uniones de cadenas
Variable cadena $a="Esta ' y \ y tambin NUL" $a="Esta \' y \\ y tambin NUL" $a="Esta es una cadena larga que presuntamente ser troceada" $a="Esta es una cadena larga que presuntamente ser troceada" $a="Esta es una cadena larga que presuntamente ser troceada" $todo="v1=Esto+sera+una+variable&v2=esto+otra&p[]=incluso+un+array" Divide la cadena $todo en sus componentes $a="Esta cadena sera devuelta en trozos" $trozo1=explode(" ",$a); echo $trozo1[0]; echo $trozo1[1]; echo $trozo1[2]; echo $trozo1[3]; echo $trozo1[4]; echo $trozo1[5]; > $trozo2=explode("a",$a); echo $trozo2[0]; echo $trozo2[1]; echo $trozo2[2]; echo $trozo2[3]; echo $trozo2[4]; Esta cadena sera devuelta en trozos Est c den ser devuelt en trozos parse_str($todo); echo $v1; echo $v2; echo $p[0]; Esto sera una variable esto otra incluso un array Sintaxis AddSlashes($a) stripslashes($a) chunk_split($a,5,"") chunk_split($a,5) chunk_split($a,76,"-") Resultado $a="Esta \' y \\ y tambin NUL" Esta ' y y tambin el nulo Esta es una cadena larga que presuntamente ser troceada Esta es un a cad ena l arga que p resun tamen te se r tr ocead a Esta es una cadena larga que presuntamente ser troceada-

Recoger en un array cada uno de los trozos delimitados por los separadores

Recoger en un array cada uno de los trozos delimitados por los separadores

echo $trozo2[5]; Recoger en un array cada uno de los trozos delimitados por los separadores hasta un mximo de 3 Anteponemos @ a print para evitar mensajes de error en los valores vacos $trozo3=explode(" ",$a,3); Esta @print $trozo3[0]; cadena @print $trozo3[1]; sera devuelta en trozos @print $trozo3[2]; @print $trozo3[3]; @print $trozo3[4]; @print $trozo3[5]; $trozo4=explode("a",$a,3); Est @print $trozo4[0]; c @print $trozo4[1]; dena sera devuelta en trozos @print $trozo4[2]; @print $trozo4[3]; @print $trozo4[4]; @print $trozo4[5]; Esta cadena sera devuelta en trozos Est* c*den* ser* devuelt* en trozos Esta-cadena-sera devuelta en trozos Est: c:dena sera devuelta en trozos Esta cadena sera devuelta en trozos Est* c*den* ser* devuelt* en trozos Esta-cadena-sera devuelta en trozos Est: c:dena sera devuelta en trozos Esta cadena ser dividida con la funcin strtok Esta cadena Esta Est c den ser dividid con l funcin strtok

Recoger en un array cada uno de los trozos delimitados por los separadores hasta un mximo de 3 Anteponemos @ a print para evitar mensajes de error en los valores vacos implode(" ",$trozo1) implode("*",$trozo2) implode("-",$trozo3) implode(":",$trozo4) join(" ",$trozo1) join("*",$trozo2) join("-",$trozo3) join(":",$trozo4) $cadena="Esta cadena ser dividida con la funcin strtok" $trocin = strtok ($cadena," "); while ($trocin) { echo "$trocin<br>"; $trocin = strtok (" "); } $trocin = strtok ($cadena," "); echo $trocin,"<br>"; $trocin1 = strtok (" "); echo $trocin1,"<br>"; $trocin2 = strtok (" "); echo $trocin2,"<br>"; $trocin = strtok ($cadena,"a"); while ($trocin) { echo "$trocin<br>"; $trocin = strtok ("a"); }

Encriptacin de cadenas
PHP dispone de funciones que permiten codificar o encriptar cadenas de caracteres. bin2hex(cadena) Devuelve una cadena ASCII que contiene la representacin hexadecimal de la cadena. La conversin se realiza byte a byte, con los 4 bits superiores primero. crypt(cadena) Devuelve la cadena encriptada utilizando una semilla aleatoria de dos caracteres. Por su caracter aleatorio, si se ejecuta dos veces seguidas tal como puedes observar en el ejemplo dar dos resultados diferentes. crypt(cadena,"xx") Devuelve la cadena encriptada utilizando como semilla los dos caracteres (entre comillas) que se escriben como segundo parmetro de la funcin. Tanto en este supuesto como en el anterior, los dos primeros caracteres de la cadena encriptada coinciden con los que han sido utilizados como semilla.

md5(cadena) Aplica el algoritmo md5 y devuelve la huella digital generada por l. Este algoritmo presenta como peculiaridades que tenga la dimensin que tenga la cadena a la que se aplique genera siempre una huella digital que no es otra cosa que una cadena formada por 32 caracteres y que no dispone de ningn mecanismo inverso. Seguramente habrs vivido esta experiencia. En muchos espacios de Internet grupos de noticias, cuentas de correo web, etctera que requieren un login y una contrasea cuando utilizas la opcin de recuperar contraseas no te envan tu contrasea anterior, sino que te generan y envan una nueva. Esto ocurre porque, por razones evidentes de seguridad, las contraseas se almacenan usando estas huellas digitales y resulta imposible recuperar los valores originales. La nica solucin en estos casos es crear una nueva contrasea (suelen hacerlo con las funciones de nmeros aleatorios), enviarla de forma automtica por correo electrnico y sustituir el valor anterior del registro de usuarios por el resultado de la codificacin md5 de la nueva contrasea. crc32(cadena) Aplica el algoritmo crc32 de comprobacin de integridad y devuelve el valor del mismo. Se utiliza muchsimo en los programas decompresin y descompresin de ficheros. Se aplica en el momento de comprimir y se incluye el valor obtenido dentro del fichero comprimido. Despus de la descompresin se vuelve a aplicar el mismo algoritmo y se comparan ambos valores. La coincidencia ser la garanta de que el fichero obtenido es idntico al original. Encriptaciones y codificaciones
Variable cadena $a="Esta es la cadena" $a="Encriptame" $a="Encriptame" $a="Encriptame" $a="Encriptame" $a="Encriptame" $a="Encriptame" $a="Encriptame" $a="Encriptame" Sintaxis bin2hex($a) crypt($a) crypt($a) crypt($a,"zq") crypt($a,"zq") crypt($a,"@$") md5($a) md5($a) crc32($a) Resultado 45737461206573206c6120636164656e610a $1$b81rcmj0$p63mW.bk0jMSf51dZiLV10 $1$ci1i4JWI$LEpFUE5kkRytnOFmXdmS// zqQ4qOeELzPFg zqQ4qOeELzPFg @$MB08wYjH9to 67c3ca0aefda2595138168a85e7b33a0 67c3ca0aefda2595138168a85e7b33a0 3166777410

Bsquedas y recuentos de caracteres


Variable cadena $a="Contando caracteres" $a="Contando caracteres" $a="Contando caracteres" $a="Pepe Perez el perverso pecador en penitencia" $a="Pepe Perez el perverso pecador enpenitencia" Sintaxis count_chars($a,0) Resultado Array

$b=count_chars($a,0); 3 echo $b[97]; $b=count_chars($a,0); 2 echo $b[ord("o")] substr_count($a,"Pe"); 2 substr_count($a,"pe"); 4

La funcin count_char($a,0) devuelve un array cuyos ndices son los cdigos ASCII de los caracteres y cuyos valores son el nmero de veces que se repite cada uno de ellos. La funcin substr_count($a,"cadena") determina el nmero de veces que aparece la cadena dentro de $a. Diferencia entre maysculas y minsculas.

Etiquetas HTML Dos interpretaciones


Recordemos que cuando un documento tiene extensin php es objeto de dos interpretaciones antes de ser visualizado en el navegador. En primer lugar es PHP quien ejecuta sus scripts y devuelve al cliente el documento resultante y, ms tarde, ser el propio navegador quien realice una segunda interpretacin del documento recibido cuyo resultado ser la visualizacin de la pgina. Cualquier salto de lnea que se inserte en un documento ser respetado por PHP y enviado al navegador, pero, como ste solo entiende como tales sus propias etiquetas <br>, no sern visualizados, aunque s estarn en el cdigo fuente de la pgina visualizada. Hemos de considerar un nuevo concepto. PHP permite utilizar algunos caracteres especiales que son transformados durante la ejecucin del script. Uno de ellos no es el nico es \n que es interpretado y convertido por el intrprete de PHP en un salto de lnea cuyo efecto ser visible en el cdigo fuente del documento enviado al navegador, pero que por no ser una etiqueta <br> no producir efecto alguno en la visualizacin de la pgina. nl2br($A)

Esta funcin inserta de forma automtica etiquetas HTML de salto de lnea (<br>). Por cada salto de lnea que exista en el texto de la cadena inserta una etiqueta <br> en la salida HTML. strtr($array,$diccionario)

Busca en la cadena $a las palabras coincidentes con los ndices del array asociativo $diccionario y las sustituye por los valoresasociados a esos ndices. get_meta_tags($a)

Devuelve un array asociativo cuyos ndices son los valores de la propiedad name de las etiquetas <meta> (escritas siempre en minsculas, sin comillas, y reemplazando, en el caso de que fuera necesario, los caracteres especiales por un guin bajo _) de la pgina web cuya direccin (absoluta o relativa) se indica en la cadena $a. Los valores de los elementos del array son los contenidos de esas etiquetas. htmlspecialchars($a)

Convierte en entidades de HTML los caracteres &, ", < y >. Con ello se consigue su visualizacin y se impide que sean interpretados como signos del lenguaje HTML. htmlentities($a) Es una funcin similar a la anterior, pero en este caso afecta a todos los caracteres que tienen equivalentes como entidad HTMLutilizando el juego de carcteres ISO-8859-1. Recuerda que son stos. Este es un ejemplo de uso de la citadas funciones

<?php /* definamos algunas variables de cadena tal como se describe en sus contenidos e incluyamos caracteres especiales \n

*/

$cadena1="Este texto est escrito en varias lneas y hemos saltado de una a otra pulsando enter";

$cadena2="Aqu\nseparamos\nlas\nlneas\ncon\nsin\npulsar\nenter"; $cadena3=<<<Prueba Nuevamente texto en varias lineas ahora usando sintaxis de documento incrustado. Seguiremos probando Prueba; $cadena4=<<<OtraPrueba Ahora\ninsertar\nalgo\ncomo\nesto OtraPrueba; # definamos una variable conteniendo saltos de linea HTML # y vayamos construyendo una variable de salida # en la que uniremos las variables anteriores insertando # entre ellas saltos de linea para facilitar la visualizacin # en el navegador $saltador="<br><br><br>"; $salida=$cadena1.$saltador; $salida .=$cadena2.$saltador; $salida .=$cadena3.$saltador; $salida .=$cadena4.$saltador; # visualicemos el resultado print $salida; #apliquemos ahora a la variable salida # la funcion nl2br y veamos el resultado print $saltador.nl2br($salida); ?>
ejemplo39.php

Si ejecutas el ejemplo y visualizas el cdigo fuente a travs del navegador podrs observar como los resultados del primer printgeneran saltos de lnea en ste. Y en el caso del cdigo correspondiente al segundo print, podrs visualizar etiquetas <BR /> que son el resultado de la aplicacin de la funcin nl2br Las cadenas y las etiquetas HTML
Cadenas $a="Esto es\nun texto escrito\n en varias lineas\nsin etiquetas<BR>"; $dicc=array ( "Lundi"=>"Lunes", "good"=>"bueno", "sun" =>"sol"); $a="Lundi es un dia good si hace sun" $a="index.php" $a="index.php" Sintaxis nl2br($a) Resultado Esto es un texto escrito en varias lineas sin etiquetas<BR> Lunes es un dia bueno si hace sol Programacin, PHP, Apache, MySQL Materiales para un curso a distancia

strtr($a,$dicc)

$b=get_meta_tags($a); echo $b['keywords'] $b=get_meta_tags($a); echo $b['description'] echo $a echo htmlspecialchars($a)

$a="<H1>A</H1>"

A
<H1>A</H1>

$a="<H1>A</H1>"

La tabla de sustituciones de htmlspecialchars es esta: Sustitye & por &amp; " por &quot;

< por &lt; > por &gt;

Operadores bit a bit Comentario previo


Incluimos la sintaxis de este tipo de operadores a ttulo meramente informativo. Rara vez ser necesario utilizarlos en nuestras aplicaciones PHP. Su utilidad suele limitarse a la gestin de perifricos y algunas operaciones de clculo de carcter muy reiterativo en la que se puede conseguir un rendimiento muy superior a los operadores tradicionales. En el mbito propio del PHP pueden tener algn inters a la hora de elaborar rutinas para encriptar el cdigo fuente de algunos scripts que por su importancia pueden requerir ese tipo de proteccin. Los que s han de resultarnos de gran inters sern el resto de los operadores. Los iremos viendo en pginas sucesivas.

Operadores bit a bit


$A & $B

El operador & compara los valores binarios de cada uno de los bits de las cadenas $A y $B y devuelve 1 en el caso que ambos sean 1, y 0 en cualquier otro caso. Cuando las variables $A y $B son cadenas compara los valores binarios de los cdigos ASCII de sus caracteres y devuelve los caracteres ASCII correspondientes al resultado de esa comparacin. El operador &
Nmeros Variables $a=12 $b=23 $a&$b=4 1100 10111 100 Nmeros como cadenas Valores binarios Variables $A="12" $B="23" $A&$B=02 Valores binarios 110001110010 110010110011 110000110010 Cadenas alfanumricas Variables $A1="Rs" $B1="aZ" $A1&$B1=@R Valores binarios 10100101110011 11000011011010 10000001010010

En los casos de cadenas hemos diferenciado en rojo el valor binario correspondiente al primer carcter. Esos valores binarios corresponden a la forma binaria del cdigo ASCII de cada uno de los caracteres

Un caso de aplicacin prctica podra se la determinacin de la condicin de par o impar de un nmero. El resultado de una comparacin $a & 1 significara que si el valor asignado a $a fuera un nmero impar su forma binaria tendra como ltimo carcter (por la derecha) un uno. Por el contrario, si fuera par ese ltimo carcter sera cero. Luego la comparacin mediante el operador & arrojara 1 (coincidencia) en el primero caso y 0 (no coincidencia en el segundo). Si ejecutamos este script: $a=13; print ($a & 1); veramos que el resultado es 1 mientras que si hiciramos lo mismo con $a=14; print ($a & 1); resultara 0. Sera una opcin alternativa a la de ver si el resto de dividir el valor de la variable entre 2 ($a=13; print ($a % 2);) es 1 (no divisible y en consecuencia impar) o si $a=14; print ($a % 2); da 0(divisible, ya que su resto es cero, y en consecuencia se trata de un nmero par). $A | $B

Funciona de forma idntica al anterior y devuelve 1 cuando al menos el valor de uno de los bits comparados es 1, y devolver 0 cuandoambos sean 0. El operador |
Nmeros Variables $a=12 Valores binarios 1100 Nmeros como cadenas Variables $A="12" Valores binarios 110001110010 Cadenas alfanumricas Variables $A1="Rs" Valores binarios 10100101110011

$b=23 $a|$b=31

10111 11111

$B="23" $A|$B=33

110010110011 110011110011

$B1="aZ" $A1|$B1=s{

11000011011010 11100111111011

Puedes observar que el tratamiento es distinto cuando los mismos valores numricos se asignan como entero y como cadena. Al asignarlos como cadena opera los valores binarios de los cdigos ASCII de los caracteres, mientras que cuando se trata de nmeros compara los valores de las expresiones binarias de los valores de cada uno de ellos $A ^ $B

Devuelve 1 cuando los bits comparados son distintos, y 0 cuando son iguales. El operador ^
Nmeros Variables $a=12 $b=23 $a^$b=27 Valores binarios 1100 10111 11011 Nmeros como cadenas Variables $A="12" $B="23" $A^$B=  Valores binarios 110001110010 110010110011 000011000001 Cadenas alfanumricas Variables $A1="Rs" $B1="aZ" $A1^$B1=3) Valores binarios 10100101110011 11000011011010 01100110101001

$A << $B

Realiza la operacin $A * 2 . Hace el clculo aadiendo $B CEROS (binarios) a la derecha de la cadena binaria $A. El operador <<
Nmeros Variables $a=12 $b=2 $a<<b=48 Valores binarios 1100 10 110000 Nmeros como cadenas Variables $A="12" $B=2 $A<<$B=48 Valores binarios 110001110010 10 110000 Cadenas alfanumricas Variables $A1="Rs" $B1=2 $A1<<$B1=0 Valores binarios 10100101110011 10

$B

El operador << multiplica el valor de la primera cadena por 2 elevado al valor de la segunda. Al ser un operador matemtico solo tiene sentido cuando ambas variables son nmeros naturales. En las cadenas alfanumricas extrae los nmeros que pudiera haber al comienzo y, en caso de no haberlos, toma valor cero. $A >> $B

Divide el valor $A entre 2 . Hace la operacin en la cadena binaria quitando $B CEROS (por la derecha) de la cadena $A. El operador >>
Nmeros Variables $a=12 $b=2 $a>>b=3 Valores binarios 1100 10 11 Nmeros como cadenas Variables $A="12" $B=2 $A>>$B=3 Valores binarios 110001110010 10 11 Cadenas alfanumricas Variables $A1="Rs" $B1=2 $A1>>$B1=0 Valores binarios 10100101110011 10

$B

Para este operador (>>) son aplicables los mismos comentarios hechos en el prrafo anterior.

~ $A

Invierte los valores de los bits de la cadena $A convirtiendo los CEROS en UNO y los UNO en CERO. El operador ~
$a=12 1100 ~$a=-13 1111111111111111111111111111111111111111111111111111111111110011

Operadores de comparacin
Si es este tu primer contacto con el mundo de la programacin es probable que ests pensando que todo esto est muy bien pero que a ti lo que te interesa es hacer cosas. En una palabra, que quieres usar PHP como herramienta para el desarrollo de tus proyectos. Esta pgina y las siguientes van a ser bsicas para el xito en ese lgico y razonable afn utilitarista. Pensemos en nuestro da a da. En cada momento de nuestra vida hacemos algo. Cada cosa que hacemos suele requerir casi siempre esta secuencia de acciones:comparar, evaluar, optar y hacer. Supongamos que queremos cambiar de coche. Lo ms prudente ser empezar por comparar las caractersticas (potencia, diseo, precio, etc.) de los diferentes modelos. Salvo en casos excepcionales, no tomaramos una decisin de compra a travs de un solo parmetro sino que haramos una evaluacin conjunta de todos esos factores (menos potencia pero mejor precio y diseo muy similar, por citar un ejemplo) y sera a travs de esa evaluacin como optaramos por una marca o modelo. Una vez ejercida la opcin y no antes sera el momento de realizar la compra del nuevo coche. PHP, y en general todos los lenguajes de programacin, disponen de herramientas que permiten emular cada uno de esos procesos de la conducta humana. Los iremos viendo en esta pgina y en las siguientes.

Operadores de comparacin
PHP dispone de los siguientes operadores de comparacin: $A == $B

El operador == compara los valores de dos variables y devuelve 1 (CIERTO) en el caso de que sean iguales y el valor NUL carcter ASCII 0 (FALSO) cuando son distintas. Mediante este operador se pueden comparar variables de distinto tipo. Para comparar una cadena con un nmero se extrae el valor entero de la cadena (si lleva dgitos al comienzo los extrae y en caso contrario le asigna el valor cero) y utiliza ese valor para hacer la comparacin. Cuando se comparan cadenas discrimina entre maysculas y minsculas ya que utiliza los cdigos ASCII de cada uno de los caracteres para hacer la comparacin que se hace de izquierda a derecha y devuelve 1 (CIERTO) slo en el caso que coincidan exactamente los contenidos de ambas cadenas. El operador ==
A $A=123 $A=123.0 $A=123 $A=123 $A=123 $A=123 $A="abc" $A="abc" $A="abc" B $B=123 $B=123 $B="123" $B="123ABC" $B=124 $B=124 $B="ABC" $B="abc" $B="abcd" Operador == == == == == == == == == Sintaxis $A==$B $A==$B $A==$B $A==$B $A==$B ord($A==$B) $A==$B $A==$B $A==$B 1 0 Resultado 1 1 1 1

Los valores de la columna sealada como Resultados se obtienen mediante la funcin echo($A==$B); Podemos ver que, en los casos que es cierta la igualdad, imprime un 1, mientras que cuando es falsa no imprime nada. Se justifica este extremo porque en caso de no coincidencia el valor devuelto es NUL (cdigo ASCII 0) y ese carcter carece de smbolo grfico. Hemos marcado en rojo una excepcin. En ese caso, la instruccin es echo ord($A==$B); y como recordars dado que ord, que devuelve el cdigo ASCII del caracter contenido en el parntesis que le acompaa, podemos comprobar a travs del cero de este resultado, que, efectivamente, la no coincidencia devuelve NUL.

$A === $B

El operador === es similar al anterior, pero realiza la comparacin en sentido estricto. Para que devuelva 1 es necesario que sean iguales los valores de las variables y tambin su tipo. El operador ===
A $A=123 $A=123.0 $A=123 $A=123 $A=123 $A=123 $A="abc" $A="abc" $A="abc" B $B=123 $B=123 $B="123" $B="123ABC" $B=124 $B=124 $B="ABC" $B="abc" $B="abcd" Operador === === === === === === === === === Sintaxis $A===$B $A===$B $A===$B $A===$B $A===$B ord($A===$B) $A===$B $A===$B $A===$B 1 0 Resultado 1

Observa que los valores sealados en rojo a diferencia de lo que ocurre con el operador anterior devuelvenNUL como resultado. En este caso no slo compara valores sino que tambin compara tipos de variables. Al ser una de ellas tipo numrico y la otra cadena alfanumrica el resultado no puede ser otro que NUL.

$A != $B

El operador != devuelve 1 cuando los valores de las variables son distintos (en general ! indica negacin, en este caso podramos leerno igual) y devuelve NUL cuando son iguales. Este operador no compara en sentido estricto, por lo que puede considerar iguales los valores de dos variables de distinto tipo. El operador !=
A $A=123 $A=123.0 $A=123 $A=123 $A=123 $A=123 $A="abc" $A="abc" $A="abc" B $B=123 $B=123 $B="123" $B="123ABC" $B=124 $B=124 $B="ABC" $B="abc" $B="abcd" Operador != != != != != != != != != Sintaxis $A!=$B $A!=$B $A!=$B $A!=$B $A!=$B ord($A!=$B) $A!=$B $A!=$B $A!=$B 1 1 49 1 Resultado

En los ejemplos sealados en rojo Puedes comprobar el carcter no estricto de este operador. Devuelve NUL porque considera que no son distintos, lo que equivale a interpretar que los considera iguales pese a que las variables sean de distinto tipo.

$A < $B

El operador < devuelve 1 cuando los valores de $A son menores que los de $B . Los criterios de comparacin son los siguientes: Los valores numricos siguen el criterio matemtico. Cuando se trata de un nmero y una cadena extrae el valor numrico de sta (cero si no hay ningn dgito al principio de la misma) y hace una comparacin matemtica. En el supuesto de dos cadenas, compara uno a uno de izquierda a derecha los cdigos ASCII de cada uno de los carcteres (primero con primero, segundo con segundo, etctera). Si al hacer esta comprobacin encuentra en la primera cadena un caracter cuyo cdigo ASCII es mayor que el correspondiente de la segunda cadena, o encuentra que todos son iguales en ambas cadenas devuelve NUL. Solo en el caso de no exitir ninguno mayor y s haber al menos uno menor devolver UNO. Cuando las cadenas tengan distinta longitud, consider (a efectos de la comparacin) que los caracteres que faltan en la cadena ms corta son NUL (ASCII 0). El operador <
A $A=123 $A=123 $A=123.0 $A=123 $A=123 $A=123 $A="abc" $A="abc" $A=" bcd" $A="aacd" $A="abc" $A="abcd" $A="A" $A="a" $A="aBC" $A="123" $A=123 B $B=123 $B="123" $B="123" $B="123ABC" $B=124 $B=124 $B="ABC" $B="abc" $B="abcd" $B="abcd" $B="abcd" $B="abc" $B="a" $B="A" $B="A" $B=124 $B="124" Operador < < < < < < < < < < < < < < < < < Sintaxis $A<$B $A<$B $A<$B $A<$B $A<$B ord($A<$B) $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B $A<$B 1 1 1 1 1 1 1 49 Resultado

Observa los ejemplos sealados en rojo. Cuando las cadenas tienen distinta longitud este operador considera que los caracteres que faltan en la cadena ms corta son NUL. Esa es la razn por la que en el primer caso devuelve CIERTO (NUL es menor que d) y el segundo FALSO (d no es menor que NUL).

$A <= $B

Se comporta de forma idntica al anterior. La nica diferencia es que ahora aceptar como ciertos los casos de igualdad tanto en el caso de nmeros como en el de cdigos ASCII. El operador <=
A $A=123 $A=123.0 $A=123 $A=123 $A=123 $A=123 B $B=123 $B=123 $B="123" $B="123ABC" $B=124 $B=124 Operador <= <= <= <= <= <= Sintaxis $A<=$B $A<=$B $A<=$B $A<=$B $A<=$B ord($A<=$B) Resultado 1 1 1 1 1 49

$A="abc" $A="abc" $A="abc" $A="A" $A="a" $A="aBC" $A="123" $A=123

$B="ABC" $B="abc" $B="abcd" $B="a" $B="A" $B="A" $B=124 $B="124"

<= <= <= <= <= <= <= <=

$A<=$B $A<=$B $A<=$B $A<=$B $A<=$B $A<=$B $A<=$B $A<=$B 1 1 1 1 1

Hemos modificado la instruccin marcada en rojo para comprobar el cdigo ASCII de caracter que devuelve, en el caso de ser cierto, el resultado de la comparacin. El valor que aparece (49) como resultado es el cdigo ASCII del carcter 1.

$A > $B

Es idntico en el modo de funcionamiento a $A < $B. Solo difiere de ste en el criterio de comparacin que ahora requerir que los valores de $A sean mayores que los de la variable $B. El operador >
A $A=123 $A=123 $A=123 $A=123 $A=123 B $B=123 $B="123" $B=124 $B=124 Operador Sintaxis > > > > > > > > > > > > $A>$B $A>$B $A>$B $A>$B ord($A>$B) 0 $A>$B $A>$B $A>$B $A>$B $A>$B $A>$B $A>$B $A>$B 1 1 1 Resultado

$B="123ABC" >

$A="abc" $B="ABC" $A="abc" $B="abc" $A="abc" $B="abcd" $A="A" $A="a" $B="a" $B="A"

$A="aBC" $B="A" $A="123" $B=124 $A=123 $B="124"

$A >= $B

Aade al anterior la posibilidad de certeza en caso de igualdad. El operador >=


A $A=123 $A=123 $A=123 $A=123 $A=123 B $B=123 $B="123" $B=124 $B=124 Operador Sintaxis >= >= >= >= >= >= >= >= >= >= >= >= $A>=$B $A>=$B $A>=$B $A>=$B ord($A>=$B) 0 $A>=$B $A>=$B $A>=$B $A>=$B $A>=$B $A>=$B $A>=$B $A>=$B 1 1 1 1 Resultado 1 1 1

$B="123ABC" >=

$A="abc" $B="ABC" $A="abc" $B="abc" $A="abc" $B="abcd" $A="A" $A="a" $B="a" $B="A"

$A="aBC" $B="A" $A="123" $B=124 $A=123 $B="124"

Operadores lgicos Operadores lgicos


Mediante operadores lgicos es posible evaluar un conjunto de variables lgicas, es decir, aquellas cuyos valores sean nicamente: VERDADERO o FALSO (1 NUL). El resultado de esa evaluacin ser siempre 1 NUL. $A AND $B

El operador AND devuelve VERDADERO (1) en el caso de que todas las variables lgicas comparadas sean verdaderas, y FALSO (NUL) cuando alguna de ellas sea falsa. El operador AND
Variables Ejemplo de sintaxis Otra sintaxis Condicin A $a>$b $a>$b $a>$b $a<$b $a<$b $a<$b $a>$b $a<$b $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas" $x=$a>$b;$y=$a>$c;$z=$a>$f; echo ($x AND $y AND $z); echo ($a>$b AND $a>$c AND $a>$f); Condicin B Condicin C A $a>$c $a>$c $a<$c $a>$c $a<$c $a>$c $a<$c $a<$c $a>$f $a<$f $a>$f $a>$f $a>$f $a<$f $a<$f $a<$f 1 1 1 1 1 1 B 1 1 1 1 1 C 1 Resultado 1

$A && $B

El operador && se comporta de forma idntica al operador AND. La nica diferencia entre ambos es que operan con distinta precedencia. Ms abajo veremos el orden de precedencia de los distintos operadores. El operador &&
Variables $a>$b $a>$b $a>$b $a<$b $a<$b $a<$b $a>$b $a<$b $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas" B 1 1 1 1 1 1 1 1 C 1 Resultado 1 $a>$c $a>$c $a<$c $a>$c $a<$c $a>$c $a<$c $a<$c $a>$f $a<$f $a>$f $a>$f $a>$f $a<$f $a<$f $a<$f 1 1 1 Condicin A Condicin B Condicin C A

$A OR $B

Para que el operador OR devuelva VERDADERO (1) es suficiente que una sola de las variables lgicas comparadas sea verdadera. nicamente devolver FALSO (NUL) cuando todas ellas sean FALSAS. El operador OR

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

$a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas" B 1 1 1 1 1 1 1 1 C 1 Resultado 1 1 1 1 1 1 1 $a>$c $a>$c $a<$c $a>$c $a<$c $a>$c $a<$c $a<$c $a>$f $a<$f $a>$f $a>$f $a>$f $a<$f $a<$f $a<$f

Condicin A Condicin B Condicin C A 1 1 1

$A || $B

El operador || se comporta de forma idntica al operador OR. Su nica diferencia es el orden de precedencia con el que opera. El operador ||
Variables $a>$b $a>$b $a>$b $a<$b $a<$b $a<$b $a>$b $a<$b $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas" B 1 1 1 1 1 1 1 1 C 1 Resultado 1 1 1 1 1 1 1 $a>$c $a>$c $a<$c $a>$c $a<$c $a>$c $a<$c $a<$c $a>$f $a<$f $a>$f $a>$f $a>$f $a<$f $a<$f $a<$f 1 1 1 Condicin A Condicin B Condicin C A

$A XOR $B

El operador XOR devuelve VERDADERO (1) slo en el caso de que sea cierta una sola de las variables, y FALSO (NUL) cuando ambas sean ciertas o ambas sean falsas. El operador XOR
Variables $a>$b $a>$b $a<$b $a<$b $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas" A 1 1 1 B 1 1 1 Resultado $a>$c $a<$c $a>$c $a<$c Condicin A Condicin B

! $A

Este operador NOT (negacin) devuelve VERDADERO (1) si la variable lgica $A es FALSA y devuelve FALSO (NUL) si el valor de esa variable $A es VERDADERO.

Sintaxis alternativa
Tal como hemos descrito los distintos operadores lgicos sera necesario que $A y $B contuvieran valores lgicos, y eso requerira un paso previo para asignarles valores de ese tipo. Habra que recurrir a procesos de este tipo:

$A = $x>$y; $B= $x >=$z; $A && $B;

pero se obtendra el mismo resultado escribiendo: $x>$y && $x >=$z;

que, aparte de ser la forma habitual de hacerlo, nos evita dos lneas de instrucciones. Aunque el propio ejemplo se auto comenta, digamos que al utilizar operadores lgicos se pueden sustituir las variables lgicas por expresiones que den como resultado ese tipo de valores.

Orden de precedencia
Cuando se usan los operadores lgicos se plantean situaciones similares a lo que ocurre con las operaciones aritmticas. Dado que permiten trabajar con secuencias de operaciones sera posible, por ejemplo, una operacin de este tipo: $a<$b OR $c<$b && $a<3

Surgiran preguntas con estas: qu comparacin se hara primero OR &&? se haran las comparaciones en el orden natural? alguno de los operadores tiene prioridad sobre el otro? Igual que en las matemticas, tambin aqu, hay un orden de prioridad que es el siguiente: NOT, &&, ||, AND, XOR y, por ltimo, OR. De esta forma la operacin && se realizara antes que ||, mientras que si pusiramos AND en vez de && sera la operacin || la que se hara antes y, por lo tanto, los resultados podran variar de un caso a otro. Aqu tambin es posible, de la misma manera que en la aritmtica, utilizar parntesis para priorizar una operacin frente a otra. Es muy importante prestar atencin a la construccin correcta de estas estructuras. Un descuido en la atencin a las prioridades puede ser origen lo es frecuentemente de resultados incoherentes que suelen ser detectados bajo una apariencia aleatoria. Ten muy en cuenta que al depurar programas no siempre se ven fcilmente este tipo de errores de programacin. Puede que para determinados valores los resultados sean los esperados y que, sin embargo, al utilizar otros distintos pueda manifestarse la incoherencia. Si te ocurriera esto no pienses que es el ordenador el que est haciendo cosas raras, procura revisar los parntesis y los criterios de prioridad de los distintos operadores contenidos en la estructura lgica.

<?php # asignemos valores a cuatro variables $a=3; $b=6; $c=9; $d=17; # utilicemos operadores de comparacin # y recojamos sus resultados en nuevas variables $x= $a<$b; $y= $a<$b; $z=$c>$b; # apliquemos un operador lgico (por ejemplo &&) # e imprimamos el resultado print("Resultado FALSO si no sale nada: ".($y && $z)."<br>");

# hagamos la misma comparacin sin utilizar la variables $y y $z # que deber darnos el mismo resultado print("<br>Resultado FALSO si no sale nada: ".($a<$b && $c> $b)."<br>"); /* veamos ahora qu ocurre al ampliar la estructura qu ocurrira si escriberamos $a <$b OR $c> $b && $d<$a ? El operador && tiene preferencia ante OR, luego hara primero la comparacin $c>$b && $d<$a 9 > 6 es cierto, 17 < 3 es falso, luego como && solo devuelve cierto cuando ambos sean ciertos el resultado de esa opcin es FALSO. Veamos qu ocurre al comparar $a<$b OR falso (resultado anterior) como 3 < 6 es cierto OR operar con cierto y falso que dar como resultado CIERTO, ya que basta que se cumpla una de las condiciones */ /* vamos a comprobarlo mediante este operador condicional no conocemos aun su sintaxis pero adelntemosla un poco... si el contenido del parntesis que va detrs del if es cierto imprimir cierto y en caso contrario imprimir falso Aqui debera imprimirnos cierto */ if($a <$b OR $c>$b && $d<$a) { print "cierto<br>"; }else{ print "falso<br>"; } # Cambiemos la estructura anterior por $a<$b || $c>$b AND $d<$a # ahora se operar primero || que como antes dar cierto # pero ese resultado operado mediante AND con falso dar FALSO # AL CAMBIAR LOS OPERADORES POR SUS SIMILARES el resultado el DISTINTO if($a<$b || $c>$b AND $d<$a) { print "cierto<br>"; }else{ print "falso<br>"; } # un parntesis nos devolver a la situacin anterior # escribamos $a<$b || ($c>$b AND $d<$a) # veremos que el resultado es CIERTO como ocurra en el primer caso if($a<$b || ($c>$b AND $d<$a)) { print "cierto<br>"; }else{ print "falso<br>"; } ?>
ejemplo40.php

Operadores de incremento Operadores de incremento


Los caracteres ++ y -- escritos al lado del nombre de una variable producen incrementos o decrementos de una unidad en el valor de la misma. De igual forma, los operadores +=n y -=n escritos a la derecha del nombre de una variable producen incrementos o decrementos de nunidades en el valor de la variable.

Como veremos a continuacin, los operadores ++ y -- se comportan de distinta forma segn estn situados a la izquierda o a laderecha de la variable. Estas operaciones slo tienen sentido en variables numricas enteras o no, pero si se aplican a variables de cadena les asignan previamente valor cero, salvo en una curiosa excepcin que puedes ver en la primera de las tablas que tienes aqu a la derecha.

Operadores de pre incremento


++$A y --$A

Este operador incrementa el valor de la variable en una unidad (+1 o -1) antes de ejecutar el contenido de la instruccin. El operador ++$A
Variables numricas Valor inicial Sintaxis $a=23 $a=23 echo ++$a 24 Variables alfanumricas Resultado Valor inicial Sintaxis $b="pepe" echo ++$b Resultado pepf

echo ++$a*2 48

$b="pepe" echo ++$b*2 0

El operador $A
Variables numricas Valor inicial Sintaxis $a=23 $a=23 echo $a 22 Variables alfanumricas Resultado Valor inicial Sintaxis $b="pepe" echo --$b Resultado pepe

echo --$a*2 44

$b="pepe" echo $b*2 0

$A+=n y $A-=n

Este operador incrementa el valor de la variable en n unidades (+n o -n) y luego ejecuta el contenido de la instruccin. El operador $A +=n
Variables numricas Valor inicial Sintaxis $a=23 $a=23 echo $a+=5; echo $a 28 28 Variables alfanumricas Resultado Valor inicial Sintaxis echo $b+=5; $b="pepe" echo $b $b="pepe" Resultado 5 5

echo 2*$a+=5; 56 echo 2*$a 56

echo 2*$b+=5; 10 echo 2*$b 10

El operador $A =n
Variables numricas Valor inicial Sintaxis $a=23 $a=23 echo $a-=5; echo $a 18 18 Variables alfanumricas Resultado Valor inicial Sintaxis echo $b-=5; $b="pepe" echo $b $b="pepe" Resultado -5 -5

echo 2*$a-=5; 36 echo 2*$a 36

echo 2*$b-=5; -10 echo 2*$b -10

Operadores de post incremento


$A++ y $A--

Cuando los operadores ++ o -- estn situados a la derecha de la variable los incrementos no se producen hasta que se ejecute lainstruccin siguiente.

El operador $A++
Valor inicial de la variable Sintaxis $a=23 $a=23 echo $a++; echo $a Resultado 23 24

echo 2*$a++; 46 echo 2*$a 48

El operador $A-Valor inicial de la variable Sintaxis $a=23 $a=23 echo $a--; echo $a Resultado 23 22

echo 2*$a--; 46 echo 2*$a 44

Operadores condicionales Operadores condicionales


Este tipo de operadores son el autntico cerebro de cualquier aplicacin que desarrollemos en PHP o en cualquier otro lenguaje de programacin. Los operadores condicionales son la herramienta que permite tomar decisiones tales como: hacer o no hacer, y tambin:hacer algo bajo determinadas condiciones y otra cosa distinta en caso de que no se cumplan. Aunque para simplificar los ejemplos vamos a utilizar en ellos una sola condicin, este operador permite incluir como tal cualquier estructura lgica, del tipo que hemos visto en la pgina anterior, por compleja que esta sea.

Alternativas de sintaxis
Como iremos viendo a lo largo de estas lneas, este operador permite diferentes formas de sintaxis que podemos utilizar segn nuestra conveniencia. La forma ms simple es: if(condicin) ..instruccin... ;

Si se cumple la condicin establecida en el parntesis se ejecutar la primera instruccin que se incluya a continuacin de ella. Cualquier otra instruccin que hubiera despus de ella no se vera afectada por el condicional ejecutndose en cualquier circunstancia.

<?php # Definamos dos variables y asignmosles valores. # Hubieran podido obteners por cualquier otro procedimiento: # desde un array, # a travs de un formulario cuya action ejecute este script, etc. $A=3; $B="3"; if ($A==$B) print ("A es igual B"); # # # # # cualquier otra instruccin que incluyramos de aqu en adelante se ejecutara independientemente de que la condicin se cumpla o no ya que esta forma de if (sin llaves) nicamente considera la primera instruccin comprobmoslo en este otro supuesto

if ($A<$B) print ("A es menor que B"); print("<br>A no es menor que b, pero esto saldr<br>"); print("Esta es la segunda instruccin. No la condicionar el if"); ?>

ejemplo41.php

if(condicin){ ..instruccin 1... ; ..instruccin 2... ; .... ; }

Es una ampliacin del caso anterior. Cuando es necesario que en caso de que se cumpla la condicin o condiciones se ejecutems de una instruccin, se aade una { para indicar que habr varias instrucciones, se escriben estas y se seala el final mediante }. if(condicin) : ..instruccin 1... ; ..instruccin 2... ; .... ; endif;

Esta otra forma del condicional se comporta como la anterior pero con otra sintaxis. Se sustituye la { de apertura por : y la } de cierre por endif

<?php $A=3; $B="3"; # en este caso cerraremos entre llaves las lneas # que deben ejecutarse si se cumple la condicin if ($A==$B){ print ("A es igual B"); echo "<br>"; echo "Este if tiene varias instrucciones contenidas entre llaves"; } # una sintaxis alternativa a las llaves # sustituyamos la { por : y la } por endif if ($A==$B): print ("A es igual B"); echo "<br>"; echo "Hemos cambiado {} por : endif"; endif; ?>
ejemplo42.php

if(condicion){ ?> ..Etiquetas HTML... ; ..HTML... ; .... ; <? } ?>

PHP permite la utilizacin del operador condicional if con esta sintaxis. Un primer script PHP establece la condicin. Todo lo contenido entre ese primer script y el de cierre: <?}?> ser cdigo HTML (est fuera del script), que se insertar en el documento slo en el caso de que se cumpla la condicin. if(condicion) : ?> ..Etiquetas HTML... ; ..HTML... ; .... ; <? endif; ?>

Idntica a la anterior, con la sintaxis : y endif.

<?php $a=5; # observa que ponemos la etiqueta de fin de script # despus de la llave de apertura if ($a==5){ ?> <!-- Aqu estamos poniendo HTML puro no estamos dentro del script PHP //--> <H1>Esto no ha sido interpretado por PHP</H1> <!-- en la lnea siguiente a este comentario volveremos a PHP para insertar la llave que indica el fin del if //--> <? } ?> <? # hagamos lo mismo cambiando {} por : endif if ($a==5): ?> <!-- Aqu estamos poniendo HTML puro no estamos dentro del script PHP //--> <H2>Esto tampoco sido interpretado por PHP</H2> <!-- en la lnea siguiente a este comentario volveremos a PHP para insertar la llave que indica el fin del if //--> <? endif; ?>
ejemplo43.php

If ... else
El operador condicional tiene una interesante ampliacin. En conjuncin con else permite aadir instrucciones que slo seran ejecutadas en caso de no cumplirse la condicin. Esta nueva opcin se habilita mediante la siguiente sintaxis: if(condicion){ ... instrucciones a ejecutar cuando se cumple la condicin } else { ... instrucciones a ejecutar cuando NO se cumple la condicin }

<?php $A=3; $B="4"; if ($A==$B){ #estas instrucciones se ejecutaran si se cumple la condicin print ("A es igual B"); echo "<br>"; echo "Este if tiene varias intrucciones"; }else{ # estas se ejecutaran en el caso de no cumplirse # las condiciones epecificadas en el fi print("A no es igual que B"); echo "<br>"; echo ("La estructura de control se ha desviado al else"); } ?>
ejemplo44.php

Permite tambin la sintaxis alternativa :, endif, aunque en este caso hay que hacer una precisin -puedes verla aqu debajo la llave de cierre que iba delante de else se elimina y no es sustituida por ningn caracter ni smbolo especial.

<?if(condicion): ?> ... cdigo HTML a incluir cuando se cumple la condicin <? else: ?> ... codigo HTML a incluir cuando NO se cumple la condicin <? endif; ?>

<?php $a=3; # observa que ponemos la etiqueta de fin de script # despus de los dos puntos if ($a==5): ?> <!-- Aqu estamos poniendo HTML puro no estamos dentro del script PHP //--> <H1>Esto no es PHP. A es igual 5</H1> <!-- en la lnea siguiente a este comentario volveremos a PHP para insertar el else seguido de dos puntos y cerramos de nuevo el script con ?>//--> <? else: ?> <!-- Aqu ms HTML para el (else) caso de que no se cumpla la condicin //--> <H2>Esto no es PHP. Es el resultado del ELSE</H2> <!-volveremos a PHP para insertar en endif que indica el fin del if //--> <? endif; ?>
ejemplo45.php

En algunos casos resulta til y cmodo el uso de esta otra posibilidad de sintaxis conocida como operador condicional ternario (condicin) ? (opcion1) : (opcion2)

Si se cumple la condicin se ejecuta la opcion1. En el caso de que no se cumpla se ejecutar la opcion2.

<?php $a=5; ($a==8) ? ($B="El valor de a es 8"): ($B="El valor de a no es 8"); echo $B; ?>
Ejemplo con a=8 Ejemplo con a=5

If ... elseif .. else


Otra posibilidad dentro de la estructura de los operadores condicionales es la inclusin de elseif. Esta es la sintaxis. Dentro del ejemplo tienes los comentarios explicativos. if(condicion1){ ... instrucciones a ejecutar cuando se cumple la condicin1 }elseif(condicion2){ ... instrucciones a ejecutar cuando se cumple la condicin2 sin cumplirse condicin1 } else { ... instrucciones a ejecutar cuando NO se cumple ni la condicin1 ni la condicion2 }

<?php $a=1; if ($a==1){ echo "El valor de la variable A es 1"; }elseif ($a==2){ echo "El valor de la variable A es 2"; }elseif ($a==3){ echo "El valor de la variable A es 3"; }else{ echo "La variable A no es 1, ni 2, ni 3"; } ?>
Ejemplo con a=3 Ejemplo con a=-7

<?php $a=1; if ($a==1): ?> <H1>A es igual a 1</H1> <? elseif($a==2): ?> <H1>A es igual a 2</H1> <? elseif($a==3): ?> <H1>A es igual a 3</H1> <? else: ?> <H1>A no es igual ni a 1, ni a 2, ni a 3</H1> <? endif; ?>
Ejemplo con a=2 Ejemplo con a=8

Condicionales anidados
El anidado no es otra cosa que el equivalente a los parntesis dentro de parntesis en las matemticas. Y este operador lo permite, con una nica condicin, que vers en esta muestra de sintaxis. if(condicin1){ ... instrucciones para le caso de que se cumpla la condicin1.... if(condicin2){ ... instrucciones cuando se cumple la condicion1 y la condicion2... } else { ...instrucciones cuando se cumple la condicion 1 y no se cumple la condicion 2 } }else{ ... instrucciones para el caso de que no se cumpla la condicion 1 }

Observa que todo el bloque if.. else... marcado en azul se cierra antes de abrir la opcin else marcada en marrn. Es obligatorio que as sea. De igual forma, podramos insertar bloques sucesivos hasta llegar a crear una estructura tan amplia como fuera necesaria. Como ves, todo un mundo de posibilidades.

La funcin exit()
PHP dispone de una funcin exit() muy til a los efectos del comentario anterior. Cuando se ejecuta exit() se interrumpe la ejecucin del script con lo que la respuesta del servidor a la peticin del cliente incluir nicamente los contenidos generados antes de su ejecucin.

La funcin switch La funcin switch


Una alternativa al uso de condicionales del tipo if es la funcin switch. Se trata de un condicional que evala una variable y, segn su valor, ejecuta unas instrucciones u otras. Su sintaxis es la siguiente: switch ( variable ) { case n1: ...instrucciones a ejecutar en el caso de que la variable sea igual a n1... case n2: ..instrucciones a ejecutar en el caso de que la variable sea igual a n2... } Cuando se usa esta sintaxis se ejecutan todas aquellas instrucciones que han sido incluidas a partir de la etiqueta en la que el valor que sigue a case coincide con el valor de la variable. Es decir, si en la expresin anterior la variable es igual a n1 se ejecutaran todas las instrucciones, tanto las que van detrs de case n1 como las que van detrs de case n2. La forma ms habitual de uso de esta funcin es esta: switch ( variable ) { case n1: ...instrucciones a ejecutar en el caso de que la variable sea igual a n1... break; case n2: ..instrucciones a ejecutar en el caso de que la variable sea igual a n2... break; }

Esta opcin incluye antes de cada nuevo case la funcin de ruptura break. Cuando PHP encuentra el break interrumpe la ejecucin yno la reanuda hasta la instruccin siguiente a la } que cierra el switch. Insertando break en cada una de las opciones case, slo se ejecutaran las instrucciones contenidas entre case num y ese break. default:

Bajo este nombre (default:) se pueden incluir dentro de la funcin switch un conjunto de instrucciones que solo sern ejecutadas en el caso de que el valor de la variable no coincida con ninguno de los case. Su comportamiento es equivalente a else en el condicional if.

Ejemplos con switch


<?php # esta es la variable que controlar la funcin switch $i=1; switch ($i) { #insertamos la etiqueta case 0 y a continuacin # las instrucciones correspondientes case 0: print "i es igual a 0 - No he puesto el break<br>"; # # # # # insertamos la etiqueta case 1 y a continuacin las instrucciones correspondientes como no hemos puesto break y en este ejemplo $i=1 se ejecutarn todas las instrucciones escritas de aqu en adelante

case 1: print "i es igual a 1 - No he puesto el break<br>"; case 2: print "i es igual a 2 - No he puesto el break<br>"; }; # ahora incluiremos break al final de las intrucciones de cada case # con ello lograremos que solo se ejecuten las intrucciones correspondientes # a cada uno de ellos switch ($i) { case 0: print "i es igual a 0 - Ahora lleva break<br>"; break; case 1: print "i es igual a 1 - Ahora lleva break<br>"; break; case 2: print "i es igual a 2 - Ahora lleva break<br>"; break; } ?>
ejemplo53.php

<?php $i=3; switch ($i) { case 0: print "La variable i es 0<br>"; break; case 1: print "La variable i es 1<br>"; break; case 2: print "La variable i es 2<br>"; break; # al intoducir default y dado que $i=3 se ejecutarn # las instrucciones contenidas aqu ya que la variable # no coincide con ninguno de los case establecidos default: print "La variable i es mayor que dos o menor que cero"; break; } ?>
ejemplo54.php

Bucles while Los bucles


La necesidad de repetir la ejecucin de instrucciones es algo habitual en el mundo de la programacin. Frente a la alternativa poco prctica de reescribir las instrucciones todos los lenguajes de programacin disponen de funciones que pueden ejecutar un bloque de instrucciones de forma repetitiva.

La instruccin while
Como ocurra en el caso de if, el parmetro condicin permite cualquier estructura lgica, y tambin dispone de distintas opciones de sintaxis.

while(condicin) ...instruccin que se ejecutar mientras se cumpla la condicin

Con esta sintaxis estaremos indicando que la instruccin siguiente (slo una instruccin) ha de ejecutarse continua y repetidamente hasta que deje de cumplirse la condicin establecida.

<?php # asignemos un valor a la variable $A $A=0; /* establezcamos la condicin menor que cinco e insertemos dentro de la instruccin algo que modifique el valor de esa variable de modo que en algn momento deje de cumplirse la condicin; de no ocurrir esto, el bucle se repetira indefinidamente en este ejemplo el autoincremento ++ de la variable har que vaya modificndose su valor*/ while ($A<5) echo "El valor de A es: ",$A++,"<br>"; # comprobemos que este while solo ejecuta una instruccin # la delimitada por el punto y coma anterior print("Esto solo aparecer una vez. While no lo incluye en su bucle"); ?>
ejemplo55.php

while(condicin) { ...instruccin que se ejecutar mientras se cumpla la condicin... ....otra ...instruccin que se ejecutar mientras se cumpla la condicin... .......... }

De forma similar a la utilizada en el caso de if, tambin en este caso, las llaves hacen la funcin de contenedores de las instrucciones cuya ejecucin debe repetirse mientras se cumpla la condicin.

<?php $A=0; /* utilicemos ahora el bucle para crear un tabla HTML empecemos escribiendo la etiqueta de apertura de esa tabla fuera del bucle (ya que esa se repite una sola vez) y utilicemos el bucle para escribir las celdas y sus contenidos */ print ("<table width=300 border=2>"); while ($A<=5){ echo "<tr><td align=center>"; print $A; # esta instruccin es importantsima # si no modificamos el valor de $A el bucle sera infinito $A++; print("</td></tr>"); } # cerremos la etiqueta table print "</table>"; ?>
ejemplo56.php

while(condicin) : ...instruccin que se ejecutar mientras se cumpla la condicin... ....otra ...instruccin que se ejecutar mientras se cumpla la condicin... ..........

endwhile;

Tambin aqu se mantiene la similitud con la sintaxis del condicional if. La llave ({) pueden sustituirse por (:) y en este caso en vez de (}) habra que escribir endwhile.

<?php # utilicemos whiles anidados para construir una tabla de $filas=5; $columnas=3; # insertemos la etiqueta de apertura de la tabla print ("<table border=2 width=400 align=center>"); # un primer while rojo que utiliza la condicin filas mayor que cero # en este caso, la variable tendr que ir disminuyendo su valor con $filas-# para escribir las etiquetas <tr> y </tr> # y el modificador de la variable filas # y un segundo while (magenta) para insertar las etiquetas correspondientes # a las celdas de cada fila while ($filas>0): echo "<tr>"; $filas--; while ($columnas>0): echo "<td>"; print "fila: ".$filas." columna: ".$columnas; print ("</td>"); $columnas--; endwhile; /* muy importante!. Tendremos que reasignar a la variable columnas su valor inicial para que pueda ser utilizado en la prxima fila ya que el bucle (magenta) va reduciendo ese valor a cero y en caso de no restaurar el viejo valor no volvera a ejecutarse ya que no cumple la condicin de ser mayor que cero */ $columnas=3; echo "</TR>"; endwhile; # por ultimo la etiqueta de cierre de la tabla print "</table>"; ?>
ejemplo57.php

Incluimos a continuacin un nuevo ejemplo en el hemos hecho una ligera modificacin del anterior incluyendo un condicional if. No incluimos aqu el cdigo fuente para evitarte la monotona de repetir ntegramente y con ligeras modificaciones el supuesto anterior. Utilizaremos un nuevo recurso de visualizacin tal como puedes comprobar si pulsas en el enlace Ver cdigo fuente. Esta opcin utiliza la funcin show_source('pagina');

que permite visualizar el cdigo fuente del documento que se indica en el parmetro 'pagina'. Es muy til para nuestros propsitos pero presenta un problema de seguridad. Si escribes en el parmetro pag la direccin completa de una web cualquiera (que tenga extensin php) se visualizar su contenido, salvo que el PHP instalado en el servidor que la aloja la tenga expresamente desactivada. Recuerda que en HTML se puede asignar el color fondo a una celda incluyendo bgcolor=RGB(x,y,z) siendo x, y ,z los valores de las componentes de cada color primario dentro de la etiqueta <TD>.
Ver nuevo ejemplo Ver cdigo fuente

while(condicin) : ?> ...etiquetas HTML que se insertaran repetidamente mientras se cumpla la condicin

..... <? endwhile; ?>

Tambin while permite cerrar el script PHP despus de (:) o de la sintaxis alternativa ({) e insertar etiquetas HTML, indicando ms tarde el final del bucle con <? } ?> o <? endwhile; ?>, segn proceda.

Whiles anidados
Una nueva similitud sintctica con if. En el caso de while tambin es posible insertar un while dentro de otro while utilizando una sintaxis de este tipo: while(condicin1): ...instruccin while(condicin2) { ...instruccin ..... } ..... endwhile;

En esta descripcin hemos utilizado dos sintaxis distintas. Por si acaso dudaras de si es necesario o no hacerlo de esa forma, te diremos que no es necesario nunca. El hecho de la anidacin no limita un pice las posibilidades de la sintaxis.

Bucles do ... while El bucle do... while


Estamos ante una variante del bucle while que hemos visto en la pgina anterior. La sintaxis es la siguiente: do { .... instruccin 1... .... instruccion2... } while(condicin) ;

Se diferencia de while en que en este caso se comprueba la condicin despus de haber ejecutado las instrucciones contenidas en el bucle, con lo cual, en el caso de que desde el comienzo no se cumplieran las condiciones establecidas en while las instrucciones del bucle se ejecutaran una vez. Respecto a la sintaxis, como puedes observar, detrs de do se inserta una llave ({) que seala el comienzo de las instrucciones pertenecientes al bucle. El final de esas instrucciones lo seala la otra llave (}) que precede a while(condicin). break

La funcin break de forma similar a lo que ocurra en el caso de switch permite interrumpir la ejecucin de bucle. Tal como puede verse en el ejemplo, podra entre otras posibilidades utilizarse para evitar la primera ejecucin de las instrucciones contenidas en el bucle, en el caso de que, desde un primer momento, no se cumplieran las condiciones establecidas en while. No lo hemos comentado en la pgina anterior pero break se comporta en el caso de while de forma idntica a la descrita aqu.

<?php $A=0; do { ++$A; echo "Valores de A usando el do: ",$A,"<br>";

} while($A<5); $B=7; do { echo "Pese a que B es mayor que 5 se ejecuta una vez. B= ",$B,"<br>"; } while($B<5); ?>
ejemplo59.php

<?php $A=500; do { if ($A>=500) { echo "No puede ejecutarse el bucle, porque no se cumple la condicion"; break; } ++$A; echo "Valores de A usando el do: ",$A,"<br>"; } while($A<500); echo "<BR>He salido del bucle porque A es: ",$A; ?>
ejemplo60.php

El ejemplo que tienes aqu debajo es similar al ejemplo n. 57 de la pgina anterior. Slo hemos sustituido los bucles while que all habamos utilizado por otros del tipo do ... while.
ejemplo61.php Ver cdigo fuente

Bucles for El bucle for


Se trata de una nueva forma de uso bastante habitual que permite establecer un bucle que se repetir mientras una variable numrica se mantenga dentro de intervalo especificado en la sintaxis del propio bucle indicndose tambin en la propia instruccin el criterio de modificacin de esa variable en cada ejecucin del bucle. La sintaxis es la siguiente: for ( desde ; hasta ; incremento ){ ......... ...instrucciones.... ......... }

El parmetro desde permite asignar un valor inicial a una variable ($var=num) que har funciones de controladora de iteraciones. El parmetro hasta establece la condicin que limita el valor mximo que puede alcanzar la variable de control y el parmetro incremento (con una sintaxis del tipo $variable++; $variable--; ++$variable; --$variable; $variable +=n o $variable =n establece los incrementos odecrementos de la variable controladora en cada iteracin del bucle. Las instrucciones contenidas entre { } sern ejecutadas cada vez que se reitere el bucle.

<?php for ($i = 1; $i <= 10; $i++) { print $i."<br>"; }

?>
ejemplo62.php

Variantes del bucle for


El bucle for permite algunas variantes respecto a su forma ms general. Son estas: for ( desde ; ; incremento ){ ......... ...instrucciones.... ......... }

En este caso se omite el valor del parmetro hasta (observa que no se omite el separador de parmetros (;) con lo que en realidad se est asignando a hasta el valor NUL. Cuando se utiliza esta sintaxis, el bucle se repetira de forma indefinida (la variable podra tomar cero como valor, pero cero es distinto de NUL) salvo que -tal como puedes ver en el ejemplo- se escriba en las instrucciones un operador condicional con una opcin de ruptura del bucle -el famoso break que ya hemos visto al estudiar la instruccin while y otras anteriores.

<?php for ($i = 1;;$i++) { if ($i > 10) { break; } print $i."<br>"; } ?>
ejemplo63.php

for ( ; ; ){ ......... ...instrucciones.... ......... }

En este caso no se inserta ningn parmetro pero si se escriben los ; delimitadores de los mismos. Si observas el ejemplo vers que el control se realiza fuera del for. El valor de la variable contador se asigna fuera del bucle, los incrementos de esa variable estn escritos en las lneas de instrucciones y llevan un operador condicional con la funcin break para permitir la salida.

<?php $i = 1; for (;;) { if ($i > 10) { break; } print $i."<br>"; $i++; } ?>
ejemplo64.php

for( desde ; hasta ; instrucciones, incremento )

Esta nueva variante de for permite insertar instrucciones a travs del tercer parmetro de la funcin. Si insertamos como tercer parmetro un conjunto de instrucciones, separadas por comas, se ejecutarn de igual forma que si estuvieran contenidas entre { y } En este caso, el modificador de la variable de control (incremento) se incluye como una instruccin ms separada por una coma de las contenidas en ese tercer parmetro de la funcin.

<?php for ($i = 1; $i <= 10; print $i."<br>", $i++) ; ?>


ejemplo65.php

for ( desde ; hasta ; incremento ): ......... ...instrucciones.... ......... endfor;

Esta sintaxis es alternativa a la primera de las descritas. Sustituye la { por dos puntos (:) y la } por endfor.

<?php for($i = 1; $i <=10;$i++) : echo $i,"<br>"; endfor; ?>


ejemplo66.php

<?php for ($i = 1; $i <= 10;$i++):?> <H1>Esto se repetir 10 veces</H1> <? endfor; ?>
ejemplo67.php

Como puedes observar en este ltimo ejemplo tambin es aplicable aqu la sintaxis de los dos sripts PHP. El primero contiene las instrucciones del bucle y el segundo seala el final del mismo. Entre ambos scripts se escribe el cdigo HTML

Cuidado! A la hora de programar bucles hay que evitar el riesgo de convertirlo en un bucle indefinido. Cuando esto ocurre el error es humano al abrir la pgina que lo contiene parecer que nuestro navegador se ha quedado colgado aunque en realidad estar esperando a que sea atendida la peticin. Si llega a plantersete ese problema, tendrs que recurrir a la socorrida solucin de pulsar ALT+CTRL+DEL para abortar la peticin del navegador.

Bucles foreach El bucle foreach


El bucle foreach es especfico de los array y aplicable a ellos tanto si son escalares como si su tipo es asociativo. Tiene dos opciones uso. Mediante una de ellas lee nicamente los valores de los elementos del array. La segunda opcin permite leer el ndice y el valor de cada elemento.

Lectura de valores
Utilizando la sintaxis:

foreach ( array as $valor ) { ...instrucciones... }

donde array es el nombre del array (sin incluir ndices ni corchetes), as es una palabra obligatoria y $valor el nombre de una variable (puede ser creada al escribir la instruccin ya que no requiere estar previamente definida) que ir recogiendo los valores de los sucesivoe elementos del array. Las instrucciones escritas entre las { } permiten el tratamiento o visualizacin de los valores obtenidos. La variable $valor no podr ser utilizada para guardar valores. Hemos de tener en cuenta que su valor se rescribe en cada iteracin del bucle y que al acabar este slo contendr el ltimo de los valores ledos.

<?php /* definimos un array escalar utilizando la sintaxis nombre del array=array (valores de los elemento separados por comas) si los valores son nmeros no es necesario encerrarlos entre comillas */ $a=array("a","b","c","d","e"); /* definamos ahora un nuevo array, esta vez asociativo utilizando la sintaxis clave => valor tal como puedes ver */ $b=array( "uno" =>"Primer valor", "dos" =>"Segundo valor", "tres" =>"Tecer valor", ); # establecemos el bucle que leer el array $a # recogiendo en la variable $pepe los valores extrados # y escribimos los valores foreach($a as $pepe) { echo $pepe,"<br>"; }; # repetimos el mismo proceso, ahora con $b que es un array asociativo foreach($b as $pepe) { echo $pepe,"<br>"; }; ?>
ejemplo68.php

Lectura de ndices y valores


Con una sintaxis como la que sigue se pueden leer no slo los valores de un array sino tambin sus ndices. foreach ( array as $indices => $valores ) { ...instrucciones... }

donde array es el nombre de la matriz, as es una palabra obligatoria, $indices es el nombre de la variable que recogern los ndices, los caracteres => (son obligatorios) son el separador entre ambas variables y, por ltimo, $valores es el nombre de la variable que recoge el valor de cada uno de los elementos del array. Tanto esta funcin como la anterior realizan una lectura secuencial que comienza en el primer valor del array.

<?php $a=array("a","b","c","d","e"); $b=array( "uno" =>"Primer valor", "dos" =>"Segundo valor", "tres" =>"Tecer valor", );

# # # #

en este caso extraeremos ndices y valores de ambos arrays usaremos $pepe para recoger los ndices y $pepe para recoger los valores y separaremos ambas variables por => que es el separador obligatorio para estos casos Valor: ",$pepa,"<br>"; Valor: ",$pepa,"<br>";

foreach($a as $pepe=>$pepa) { echo "Indice: ",$pepe," }; foreach($b as $pepe=>$pepa) { echo "Indice: ",$pepe," }; ?>
ejemplo69.php

Arrays bidimensionales
Cuando se trata de arrays bidimensionales la lectura de los valores que contienen sus elementos requiere el uso de dos buclesanidados. Cuando un array de este tipo es sometido al bucle foreach se extrae como ndice el primero de los indices y como valor un array unidimensional que tiene como ndice el segundo de los del array original y como valor el de aquel. La lectura de los valores de cada elemento requiere utilizar un segundo bucle que extraiga la informacin del array unidimensional obtenido como valor en la primera lectura. La sintaxis sera de este tipo: foreach ($array as $indice1=>$nuevo_array) { foreach($nuevo_array as $indice2 => $valor) { .... $indice1 es el primer ndice.... .... $indice2 es el segundo ndice.... .... $nuevo_array nuevo array ..... $valor es el valor .... } }

En el caso de arrays con dimensiones superiores sera necesario proceder del mismo modo, y habra que utilizar tantos buclesforeach como ndices contuviera el array.

<?php # definamos un array bidimensional $z=array( 0 => array ( 0 => 34, 1 => 35, 2 => 36, ), 1 => array ( 0 => 134, 1 => 135, 2 => 136, ) ); # intentemos leer ndices y valores mediante un bucle foreach # y veamos como los valores que extraemos son Arrays (unidimensionales) # consecuencia del caracter bidimensional del array original

foreach($z as $pepe=>$pepa) { echo "Indice: ",$pepe," Valor: ",$pepa,"<br>"; }; /* anidemos dos bucles foreach de la siguiente forma en el primero extraemos un array que es tratado por el segundo foreach para extraer el segundo ndice y el valor realmente contenido en ese elemento bidimensional */ foreach($z as $ind1=>$valor1) { foreach($valor1 as $ind2=>$valorReal) { echo "Ind. 1: ",$ind1,"Ind. 2: ",$ind2," Valor: ",$valorReal,"<br>"; }; }; ?>
ejemplo70.php

La instruccin continue La instruccin continue


Si la instruccin break permite interrumpir el desarrollo de un bucle, mediante continue se puede impedir que, bajo unas condiciones determinadas, se ejecuten algunas o todas las instrucciones de un bucle sin que por ello se interrumpa la ejecucin de las iteraciones siguientes. Esta instruccin es aplicable tanto a bucles for como a los de tipo while o do while. Seguramente los ejemplos nos ayudarn a aclarar un poco ms la idea. En este primer ejemplo (un bucle for) tiene comocondicin(if): $i % 2 == 0 que, como recordars, significa que el resto de la divisin de $i entre dos($i % 2) sea igual (==) a cero. En este supuesto (condicin de mltiplo de dos) se activar la opcin continue y por lo tanto en esa iteracin no se ejecuta la instruccin echo y en consecuencia no se imprimirn en pantalla los mltiplos de 2.

<?php for ($i=0;$i<=10;$i++){ #condicin de mltiplo de 2 if ($i % 2 ==0 ) { continue ; } echo "La variable I vale ",$i,"<br>"; } ?>
ejemplo71.php

Este otro ejemplo (caso de bucle while) la condicin establecida para que se ejecute continue es que el valor de la variable no sea mltiplo de tres, en cuyo caso echo slo imprimir los mltiplos de 3.

<?php $i = 0; while ($i++ < 14) { #condicin de no mltiplo de 3 usando para distinto la sintaxis != if ($i % 3 !=0){ continue ; }

echo "El valor de i es: ",$i,"<br>"; } ?>


ejemplo72.php

En este nuevo ejemplo utilzaremos un bucle do ... while para presentar en pantalla los mltiplos de 11.

<?php $i = 0; do { # condicin de no mltiplo de 11. fjate en la sintaxis alternativa # observa que aqu distinto lo hemos escrito <> if ($i % 11 <>0 ){ continue ; } echo "El valor de i es: ",$i,"<br>"; }while ($i++ < 100) ?>
ejemplo73.php

La instruccin continue n
La instruccin continue puede utilizar un parmetro n con valor entero positivo que, cuando no se indica de forma expresa, toma por defecto el valor 1. La idea es la siguiente. Cuando tenemos bucles anidados el intrprete de PHP los considera numerados correlativamentede dentro hacia fuera a partir de UNO. Cuando se ejecuta continue n se redirecciona la iteracin al bucle cuyo nmero coincide con el valor de n. Obviamente, el valor de nno puede ser nunca mayor que el nmero de bucles anidados en el script. Analicemos algunos ejemplos. En este caso el bucle for sera el nmero UNO y el while sera el nmero DOS. Cuando se cumpla la condicin que activa continue 2 ($i=3) se redirecciona la iteracin al paso siguiente de while (bucle nmero DOS).

<?php $j=0; while (++$j <5) { for($i=1;$i<5;$i++){ if ($i==3){ continue 2; } echo "El valor de j es: ",$j, " y el de i es: ",$i,"<br>"; } } ?>
Caso continue 1 Caso continue 2

En este otro ejemplo hemos anidado a tres niveles y hemos escrito continue 3, aunque a la hora de ejecutar los ejemplos podrs ver las tres variantes posibles de ese script modificando los valores de continue n.

<?php $j=0;$k=0; do { //n=3 while (++$j <=5) { // n=2 for($i=1;$i<=5;$i++){ // n=1 if ($i==2){continue 3;} echo "El valor de k es: ",$k," y el valor de j es: ",$j, " y el de i es: ",$i,"<br>"; } } }while ($k++ <=5); ?>
Caso continue 1 Caso continue 2 Caso continue 3

Expresiones regulares Bsqueda y reemplazamiento de textos


PHP dispone de varias opciones para realizar tareas de bsqueda y reemplazamiento de textos. La ms antigua, POSIX (PortableOperating System Interface uniX), se anuncia como deprecated a partir de PHP 5.3. Por esa razn centraremos nuestro anlisis en la llamadaPCRE (Perl Compatible Regular Expressions) que parece ser la opcin con ms futuro. Una expresin regular o patrn de bsqueda, es una forma de describir un conjunto de cadenas de carcteres sin enumerar sus elementos. En el caso de las expresiones regulares compatibles con Perl (PCRE) hemos de empezar diciendo que han tener sealado su comienzo y su final por dos caracteres idnticos llamados delimitadores pudiendo realizar esa funcin cualquier carcter no alfanumrico. Expresiones tales como: #tomate#, *tomate* o /tomate/ seran patrones vlidos, delimitados por #, * o /, para la bsqueda de la palabra tomate. Empezaremos considerando el caso de que una coincidencia requiera encontrar una identidad plena con el patrn. Ms adelante incidiremos sobre el tema de los patrones de bsqueda y el manejo de su amplsimo abanico de opciones. Aunque lo trataremos con detalle un poco ms adelante vamos a empezar a manejar el modificador i. Cuando este carcter es aadido detrs del ltimo delimitador modifica el patrn de bsqueda para considerar las coincidencias sin hacer distincin entre maysculas y minsculas. Si no se incluyera i la bsqueda atendera al criterio de que mayscula y minscula son caracteres diferentes.

El reemplazamiento
Para poder ilustrar de forma grfica las caractersticas de los diferentes patrones de bsqueda empezaremos por conocer el manejo de la funcin: preg_replace ( patron, sustituta, cadena, limite_coincidencias, $contador ) dnde patron es el patrn de bsqueda, sustituta la cadena que va a sustituir las coincidencias, cadena la cadena en la que pretendemos realizar la bsqueda y sustitucin, limite_coincidencias el nmero mximo de coincidencias a las que aplicaremos el reemplazamiento y $contador ser el nombre de una variable que puede utilizarse como contador del nmero de cambios efectuados.

<?php /* definimos la cadena en la que pretendemos realizar la bsqueda y sustitucin */ $original = <<<Cadena Esta es la cadena que utilizaremos como original. Sobre ella efectuaremos algunos cambios utilizando EXPRESIONES REGULARES

Cadena; /*establecemos lo que queremos buscar*/ $buscar="es"; /*establecemos lo que queremos sustituya a lo anterior que ser marcar en rojo con fondo amarillo los mismos caracteres*/ $sustituto="<span style='color:red;background-color:yellow'>es</span>"; /*elegimos un delimitador para el patrn de bsqueda ( / ) */ $delimitador="/"; /* establecemos el modificador i para buscar sin diferencias maysculas de minsculas */ $modificador="i"; /* recogemos en la variable $patron la expresin regular formada por el delimitador inicial, la cadena a buscar, el delimitador final y, en este caso, el modificador i */ $patron=$delimitador.$buscar.$delimitador.$modificador; print "<br />Mediante el patrn de bsqueda: <b><i>".$patron."</i></b>"; print " buscaremos <b><i>".$buscar."</i></b> en la cadena:<br />"; print "<i>".$original."</i><br>"; print " reemplazando <b><i>".$buscar."</i></b> por "; print "<b><i>".$sustituto."</i></b><br />"; print " Este es el resultado: <b><br />"; print preg_replace ($patron,$sustituto,$original); print "</b><br /><br />"; print "Agregemos una restriccin en cuanto a coincidencias (1)<br /><b>"; print preg_replace ($patron,$sustituto,$original,1); print "</b><br /><br />Incluyamos un contador de coincidencias <br><b>"; print preg_replace ($patron,$sustituto,$original,-1,$z); print "</b><br /><br />Hemos realizado ".$z." cambios"; /* cambiemos el modificador para que sea sensible a maysculas/minusculas */ $modificador=""; /* actualicemos la variable patrn con el ltimo cambio */ $patron=$delimitador.$buscar.$delimitador.$modificador; print "<br /><b>Bsqueda sensible a maysculas/minsculas</b><br>"; print "<br />Mediante el patrn de bsqueda: <b><i>".$patron."</i></b>"; print " buscaremos <b><i>".$buscar."</i></b> en la cadena:"; print "<i>".$original."</i><br>"; print " reemplazando <b><i>".$buscar."</i></b> por "; print "<b><i>".$sustituto."</i></b>"; print " Este es el resultado: <b>"; print preg_replace ($patron,$sustituto,$original); print "</b><br /><br />"; print "Agregemos una restriccin en cuanto a coincidencias (1)<br /><b>"; print preg_replace ($patron,$sustituto,$original,1); print "</b><br /><br />Incluyamos un contador de coincidencias <br><b>"; print preg_replace ($patron,$sustituto,$original,-1,$z); print "</b><br /><br />Hemos realizado ".$z." cambios"; ?>
ejemplo79.php

Si se omiten los parmetros limite_coincidencias y $contador se reemplazarn todos los valores posibles sin recoger en ninguna variable el nmero de cambios. En el caso de que queramos indicar de forma explcita que se efecten todos los cambios posibles asignaremos al cuarto parmetro (limite_coincidencias) el valor -1. El parmetro patron puede ser un array en el que cada elemento ser un patrn de bsqueda. Cuando se da esa circunstancia ysustituta es una cadena, las coincidencias de cada uno de los diferentes patrones son reemplazadas por la cadena sustituta. En el caso de que sustituta fuera un array, las coincidencias del patron contenido en cada elemento de array sern reemplazadas por el valor del elemento de sustituta de igual ndice tal como puede verse en los ejemplos de la tabla que incluimos a

continuacin. Hemos utilizado en todos los casos el modificador i razn por la cual las bsquedas sern insensibles a maysculas y minsculas.
Cdigo Ver fuente ejemplo Ver Ver Ver Probar Probar Probar

Funcin preg_replace($patron, $sustituto, $original) preg_replace($patron, $sustituto, $original,n) $contador=0; preg_replace($patron, $sustituto, $original, -1, $contador) $patron=array('/xxx/','/yyy/'); preg_replace($patron, $sustituto, $original) $patron=array('/xxx/','/yyy/'); preg_replace($patron, $sustituto, $original,n) $contador=0; $patron=array('/xxx/','/yyy/'); preg_replace($patron, $sustituto, $original,n,$contador) $contador=0; $patron=array('/xxx/','/yyy/'); $sustituto=array('/zzz/','/ppp/');preg_replace($patron, $sustituto, $original) $contador=0; $patron=array('/xxx/','/yyy/'); $sustituto=array('/zzz/','/ppp/');preg_replace($patron, $sustituto, $original) $contador=0; $patron=array('/xxx/','/yyy/'); $sustituto=array('/zzz/','/ppp/');preg_replace($patron, $sustituto, $original)

Descripcin Devuelve una cadena sistituyendo, sin lmite de coincidencias, el contenido del patrn por la cadena de reemplazamiento Devuelve una cadena sistituyendo el contenido. El cuarto parmetro (n) establece que solo se reemplazarn las n primeras coincidencias Devuelve una cadena sistituyendo el contenido. El cuarto parmetro (-1) establece que se reemplazarn todas las coincidencias. La variable contador, incluida como quinto parmetro recoge el nmero de ocurrencias Cuando el patrn es un array (cada elemento ha de incluir los delimitadores) se sustituye cada coincidencia con cualquiera de los elementos del array por la cadena de reemplazamiento En el caso de un patrn en forma de array el lmite de coincidencias trata individualmente cada elemento del array Si se incluye el parmetro contador se cuantificarn todos los cambios realizados. Aqu utilizaremos dos arrays. Uno para establecer los patrones y otro para establecer los reemplazamientos asociados con aquellos

Ver Ver Ver

Probar Probar Probar

Ver

Probar

Cuando el patron es un array de mayor longitud que el sustituto las sustituciones Ver no definidas sern consideradas como cadenas vacas

Probar

Cuando el patron es un array de menor longitud que el sustituto los elementos sobrantes de este no producirn ningn efecto

Ver

Probar

Patrones de bsqueda
La autntica potencia de las expresiones regulares radica en el enorme abanico de opciones bsqueda que se pueden configurar utilizando: metacaracteres, indicadores de codicia, secuencias de escape, anclas, indicadores de alternancia, agrupadores, subpatrones y los diferentes tipos de modificadores. Veamos la utilidad de cada una de estas herramientas.

Metacaracteres
Llamaremos metacaracteres a un conjunto de carcteres que tienen un significado especial cuando se incluyen en una expresin regular. A ttulo puramente enumerativo, forman parte de ese conjunto los siguientes: ., +, *, {, }, [, ], -, \, ^, $, |, (, ) y ?. Veamos sus significados: . Cuando incluimos un punto como metacaracter en un patrn de bsqueda estamos indicado que se admite cualquier carcter en la posicin que ocupa el punto. Es decir, el patrn p. considerara coincidencia tanto pa, como pz, como p3. + Cuando un patrn incluye un signo ms se est especificando que el carcter que le precede puede repetirse una o ms veces. Es decir pa+ considerara coincidencias a: pa, paa, paaa y tambin a paaaaaaa. * Este metacaracter es ligeramente diferente al anterior. Tambin permite repeticiones pero no obliga a que aparezca el carcter que le precede. Es decir, el patrn pa* considerara coincidencias a: pa, paa, paaa y tambin p3 y pz que no incluyen ninguna a detrs de la p.

{m,n} Cuando se incluyen esta expresin (en la que m y n son dos nmeros naturales) a continuacin de un caracter cualquiera se especifica que se considerar coincidencia cualquier cadena que contenga ese carcter repetido un nmero veces comprendido entre m y n ambos inclusive. Quiere decir que pa{3,5} considerar coincidencias a paaa, paaaa y paaaaa pero no considerar tal coincidencia en el caso de paa o de paaaaaa. Existen casos particulares. Cuando se incluye {m} se est estableciendo que solo se considerar coincidencia cuando el caracter se repita exactamente m veces. Si se especifica {m,} (se incluye la coma pero falta el segundo valor) estaremos indicando que seconsiderar coincidencia cuando el carcter se repita m o ms veces. [] Mediante los corchetes se pueden incluir rangos de caracteres en el patrn de bsqueda. Si se especifican letras o nmeros sin ningn separador se considerar coincidencia cualquiera de ellos. Si se separan por medio de un guin dos nmeros o dos letras se considerar coincidencia cualquiera del rango delimitado por ellos. Puedes verlo en los ejemplos. ^ Cuando este smbolo (acento circunflejo) se incluye como primer carcter dentro de un corchete ser interpretado como negacin, es decir, no se considerar coincidencia la expresin que le preceda.
Patrn de bsqueda Cdigo fuente Ver Ver Ver Ver Ver Ver Ver ejemplo Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar

Descripcin Escribe una "o" marcada con colores sustituyendo a cada "o" de la cadena original sin diferenciar maysculas de minsculas. Es idntico al caso del los ejemplos anteriores Considerar coincidencias todas las d junto su carcter siguiente sea cual fuere (el punto indica que puede ser un carcter cualquiera). Cada coincidencia la reemplazar por do sin diferenciar maysculas de minsculas Considerar coincidencias todas las "d" seguida de una "o" repetida cero o ms veces. Cada coincidencia ser reemplazada por "do" Considerar coincidencia cada "d" seguida de una "o" repetida una o ms veces y reemplazar cada coincidencia por "do" Considerar coincidencia tres "o" consecutivas (ooo) y reemplazar cada coincidencia por una "a" Considerar coincidencia cada uno de los grupos cada "o", "oo", "ooo..." sin importar cuantas "o" formen el grupo reemplazando cada coincidencia por una "o" coloreada

o d. do* do+ o{3} o{1,} o{2,4} [abcd] [^abcd] [a-h] [^a-h] [0-9] [^0-9]

Considerar coincidencia los grupos "oo", "ooo" "oooo" (entre 2 y 4 repeticiones) y reemplazar por por una "a" cada una Ver de las coincidencias Considera coincidencia uno cualquiera de los caracteres incluidos en el corchete y las sustituye por * Considera coincidencia cualquiera de los caracteres distintos a los incluidos en el corchete y sustituir cada una de ellas por un * Considera coincidencia cualquier caracter comprendido entre a y h (ambos inclusive) Considera coincidencia cualquier caracter no comprendido entre a y h (ambos inclusive) Considera coincidencia cualquier dgito comprendido entre 0 y 9 (ambos inclusive) Considera coincidencia cualquier dgito no comprendido entre 0 y 9 (ambos inclusive) Ver Ver Ver Ver Ver Ver

Cuando se utilizan expresiones del tipo[0-9], [A-Z] los extremos de los intervalos se delimitan por los valores de los cdigos ASCII del primero y ltimo de los caracteres entendiendo como valores pertenencientes a ese rango aquellos carcteres cuyo cdigo ASCII pertenezca a ese intervalo. El cdigo ASCII de A es 65, el de Z es 90, el de a es 97 y el de z es 122. Hemos de prestar mucha atencin a los extremos ya que si estableciramos un rango como [a-Z] estaramos indicando un intervalo inaceptable ya que comenzara en 97 y acabara en 90 (ha de ser siempre mayor el segundo valor que el primero) y nos dara error tal como puedes ver en este enlace

Los signos utilizados como metacaracteres pueden plantear problemas en los casos en los que pretendamos incluirlos como un carcter ms en un patrn de bsqueda. Para utilizarlos de esta forma es necesario escaparlos, es decir, anteponerles el carcter \. De esa forma seran interpretados como texto. Adems de la utilidad mencionada en los prrafos anteriores, cuando se antepone el carcter de escape a algunos carcteres (distintos de los metacaracteres) se activan algunas condiciones especiales tal como puedes ver en la tabla de ejemplos que tienes a la derecha. La funcin: $r= preg_quote($c, $d) recoge en la variable $r el resultado de aplicar esa secuencia de escape a la cadena contenida como parmetro en la variable $c. El parmetro $d deber recoger el carcter delimitador del patrn de bsqueda.

En esta tabla recogemos algunos ejemplos del uso de las secuencias de escape en los patrones de bsqueda.
Patrn de bsqueda Cdigo Ver fuente ejemplo Ver Ver Ver Ver Probar Probar Probar Probar Probar Probar Probar Probar Probar

Descripcin Considera coincidencia cualquier caracter que sea un dgito comprendido entre 0 y 9 (ambos inclusive). Equivale a [0-9] Considera coincidencia cualquier caracter que no sea un dgito comprendido entre 0 y 9 (ambos inclusive). Equivale a [^09] Considera coincidencia los espacios en blanco Considera coincidencia cualquier caracter que no sea un espacio en blanco

\d \D \s \S \w \W \n \/

Considera coincidencia cualquier carcter de la "a" a la "z" (excluyendo la y caracteres con tilde) o cualquier nmero del 0 Ver al 9. No incluye los espacios entre las coincidencias Considera NO COINCIDENCIA cualquier carcter de la "a" a la "z" (excluyendo la y caracteres con tilde) o cualquier nmero del 0 al 9 Considera coincidencia los saltos de lnea (no se consideran como tal las etiquetas <br>) Al anteponerle el \ a un metacaracter es considerado como un carcter normal en la cadena de bsqueda. Si no lo hiciramos nos dara un mensaje de error En este ejemplo puede verse la utilidad de la funcin preg_quote Ver Ver Ver Ver

Alternacias
La alternancia utiliza el carcter | para permitir una eleccin entre dos o ms alternativas. Cuando se conjugan incluidas entre parntesis y teniendo en cuenta que los parntesis pueden agruparse y/o anidarse pueden construirse expresiones tan complejas como necesitemos.
Patrn de bsqueda Cdigo Ver fuente ejemplo Ver Ver Probar Probar

Representa a Se considera coincidencia la presencia de uno cualquiera de los caracteres. Todas la coincidencias se reemplazarn por * Se considera coincidencia la presencia de uno cualquiera de los caracteres del primer parntesis segudio de uno de los caracteres del segundo. Sern coincidencias: ac, ad, bc y bd. Todas la coincidencias se reemplazarn por *

a|b|c (a|b)(c|d)

Anclas
En los ejemplos que hemos visto hasta ahora las coincidencias podran producirse en cualquier parte de la cadena en la que efectuamos la bsqueda. Estas condiciones pueden modificarse restringiendo la bsqueda al principio o al final de la cadena de bsqueda. Para el primer caso se antepone al patrn el metacaracter ^.

Cuidado! El metacaracter ^ tiene dos utilidades manifiestamente distintas. Dentro de un corchete [^a] significa negacin (no igual a 'a' en este caso) y fuera de l y como primer carcter del patrn ^[abc] o ^pepe hace labores de ancla para restringir la bsqueda al principio de la cadena.

El uso del modificador A produce el mismo efecto que el metacaracter ^. Cuando se trata de buscar coincidencias nicamente al final de la cadena es necesario recurrir al metacarcter $ que debe ser incluido detrs del patrn de bsqueda. Tanto este metacarcter como ^ cambian su funcionalidad cuando se incluye el modificador m. Cuando se da esta situacin considerar comienzo y final tanto el comienzo y el final de la cadena como las posiciones anteriores y posteriores al carcter de salto de lnea \n tal como puedes ver en algunos de los ejemplos de la tabla siguiente.
Patrn de bsqueda Cdigo Ver fuente ejemplo Ver Ver Probar Probar

Representa a Considera coincidencia slo si uno de los caracteres incluidos en el corchete aparece al comienzo de la cadena Utilizando el modificador A en el patrn (en este caso incluimos los caracteres delimitadores en el patrn) se logra el

^[abcd] /[abcd]/A

mismo objetivo que en el ejemplo anterior

[abcd]$ /^[abcd]/mi /[abcd]$/mi

Considera de los caracteres incluidos entre corchetes al final de la cadena Utilizando el modificador m en el patrn se comprueban las coincidencias de los caracteres situados al comienzo de cada lnea. Se considera perteneciente a una nueva lnea cada el carcter que vaya inmediatamente despus de la secuencia \n

Ver Ver

Probar Probar Probar

Utilizando el modificador m en el patrn se comprueban las coincidencias de los caracteres situados al final de cada lnea. Ver Se considera ltimo carcter de una lnea al que precede a la secuencia \n

Codicia
Se dice que las expresiones regulares son codiciosas porque, salvo que se especifique lo contrario, procuran que la coincidencia abarque el mayor nmero de caracteres posibles. Eso significara que un patrn de bsqueda del tipo a.*z considerar como una sola coincidencia la porcin de texto delimitado por la primera "a" de la cadena y la ltima "z". La codicia puede invertirse de dos maneras. Una de ellas es modificar el patrn de bsqueda agregando el signo ? inmediatamente despus de un indicador de repeticiones (+,* o {m,n}). De esa forma a.*?z considerara como coincidencia la porcin de texto delimitado por cada "a" de la cadena y la primera de las "z" que aparezcan despus de ella. La segunda forma de invertir la codicia es agregar el modificador U con lo cual la cadena patrn podra ser similar a esta: /a.*z/U con los mismos resultados descritos en el prrafo anterior.
ejemplo119.php Ver cdigo fuente

Subpatrones
Cuando una expresin regular se encierra en un parntesis pasa a constituir un subpatrn de captura que, por defecto, tiene dos utilidades prcticas. La primera es su condicin de ser parte del patrn que la contenga incluidas las eventuales condiciones de alternancia(a|b) que pueda contener. Junto con esa funcin los subpatrones disponen de otra muy importante: la captura. Las coincidencias son almacenadas en memoria con la opcin de poder ser utilizadas a travs de lo que se conoce como retro referencias. Fuera de una clase carcter, una barra invertida seguida por un dgito mayor que 0 es una retro-referencia a un subpatrn de captura anterior. La retro-referencia no recoge el subpatrn sino el valor de la cadena coincidente con el subpatrn al que alude. Las retro referencias pueden marcarse as: \\n, \\gn o \\g{n} siendo en los tres casos n el nmero de orden del subpatrn contando de izquierda a derecha. Veamos su comportamiento con un ejemplo. Si comparamos la cadena "Me gusta el atn rojo con tomate" con el patrn el((atn|bonito)(blanco|rojo)) vamos a encontrar una coincidencia del patrn completo (atn rojo), y las coincidencias de cada uno de los subpatrones: atn en el caso del primero, y rojo en el caso del segundo. Tales coincidencias son numeradas para su uso como retro referencias por medio de nmeros naturales 1, 2 y 3 que se corresponden con los parntesis contados de izquierda a derecha. Por ese criterio de asignacin la retro referencia \1 (siempre se antepone \ para aludir a ellas) recoger el valor atn rojo, \2 contendratn y \3 incluir rojo. Hay situaciones en las que no es necesario usar retro referencias y, dado que pueden ralentizar la operacin y requerir abundante espacio de memoria, puede resulte conveniente desactivarlas. Para ello basta con que incluyamos despus del parntesis de apertura del patrn (o del subpatrn) los metacaracteres ?:. Aqu tienes algunos ejemplos de utilizacin de retro referencias.
Cdigo Ver fuente ejemplo Ver Ver Ver Probar Probar Probar

Patrn de bsqueda

Representa a El subpatrn buscar el carcter a o b. El resultado ser capturado como \1. Incluyendo la referencia a esa captura como carcter siguiente sern coincidentes con el patrn las cadenas aa y bb. El primer carcter ser una letra nmero (\w) que ha de coincidir con el cuarto carcter de la cadena (\\1). El segundo puede ser tambin cualquier letra (\w) que ha de coincidir con el tercer carcter de la cadena(\\2) El primer subpatrn (identificado mediante \1) sera el ms exterior de todos (marcado en rojo). Incluye dos

(a|b)\\1 (\w)(\w)\\2\\1 ((\w)(\w))\\3\\2\\1

subpatrones que numerados de izquierda a derecha resultarn identificados por \\2 y \\3 (verde y azul respectivamente)

((a|b)(c|d))\\1 (?:a|b)\\1 (?:a|b) ((?:a|b)(?:c|d))\\1

El primer subpatrn ha de contener una de las cadenas ac, ad, bc, o bd y, adems ha de repetirse (\\1) por tanto sern coincidencias: acac, adad, bcbc y bdbd Dar error ya que ?: es el indicador de no captura lo cual hace invlida la referencia \\1 Eliminando la retroreferencia \\1 del ejemplo anterior funciona correctamente Funciona exactamente igual que el ltimo ejemplo de la tabla anterior. Las referencias eliminadas no estn incluidas en el patrn de bsqueda y por tanto no influyen en el resultado

Ver Ver Ver Ver

Probar Probar Probar Probar

Subpatrones especiales
Subpatrones modificadores
Entre los tipos especiales de subpatrones cabe hablar de los conocidos como subpatrones modificadores. Su funcin es la deincluir o excluir modificadores a lo largo del patrn de bsqueda. Dada su condicin de subpatrones han de comienzar y terminar por parntesis (). Por su carcter especial han de llevar ? despus del parntesis de apertura (?) y a continuacin pueden incluir uno o varios modificadores. Si se trata de activarlo basta con poner el carcter representativo (A, i, m, etctera) y para desactivarlos se incluye un signo menos (-) delante de ese carcter. Por ejemplo (?A-im) activara el modificador A, desactivara el i y activara el m siempre a partir de la posicin del patrn de bsqueda en el que es incluido este subpatrn.
Subpatrones modificadores Patrn de bsqueda Representa a El primer subpatrn activa la opcin sensible a maysculas/minsculas y la aplica al primer carcter. Para los siguientes caracteres el subpatron (?i) vuelve a desactivar esa opcin. Cdigo Ver fuente ejemplo Ver Probar

(?-i)[A-Z](?i)[a-z]*

Subpatrones con aserciones


Otra situacin especial es el caso de las aserciones. En este caso se contemplan cuatro posibilidades. En subpatrn y(?=x) donde xe y son condiciones, exige que se cumpla la condicin x inmediatamente despus de hacerlo la condicin y. Si cambiramos el signo = por! la expresin y(?!x) ser interpretada como exigencia de que NO se cumpla la condicin x despus de hacerlo la condicin y Anteponiendo un < al signo = (o a !) podran plantearse expresiones del tipo (?<=x)y (?<!x)y que seran exigencias del cumplimiento (o no cumplirse si se trata de !) de la condicin x inmediatamente antes de que se cumpla la condicin y.
Comprobacin de los caracteres siguientes o anteriores - Aserciones o declaraciones Patrn de bsqueda Representa a Cdigo Ver fuente ejemplo Probar Probar Probar Probar

(?<=[0-9])[a-z] (?<![0-9])[a-z] [0-9](?=[A-Z]) [0-9](?![A-Z])

Considera coincidencia cualquier letra ([a-z]) qu est situada detrs de un nmero comprendido entre Ver 0 y 9 ([0-9]) Considera coincidencias cualquier letra ([a-z]) qu NO EST situada detrs de un nmero comprendido entre 0 y 9 ([0-9]) Considera coincidencia cualquier nmero ([0-9]) qu vaya delante (lleve detrs) de una letra ([A-Z]) Ver Ver

Considera coincidencia cualquier nmero ([0-9]) qu NO VAYA delante (NO lleve detrs) una letra ([AVer Z])

Subpatrones condicionales
Tambin existen los subpatrones condicionales que se comportan de una forma similar a los operadores condicionales. Mediante la sintaxis (?(x)y|z) o (?(x)y) se establecen dos posibilidades de coincidencia. Cuando se cumple la condicin x ser usado el patrn de bsqueda(o subpatrn) x. En caso de que no se cumpla la condicin se utilizara, en caso de haber sido especificado, el patrn z.

Las condiciones slo pueden ser establecidas por retro referencias o mediante aserciones. Cuando se utilizan retro referencias no se aluden de la forma tradicional (\\n, \\gn o \\g{n}). En este caso bastara incluir dentro del parntesis que contiene la condicin x el nmero de la retro referencia (n) sin anteponerle ningn otro carcter. Puedes verlo en los ejemplos de la tabla. En la tabla que tienes a continuacin hemos incluido una serie de ejemplos que contemplan algunas de las mltiples posibilidades que ofrecen los subpatrones condicionales. Es particularmente importante prestar mucha atencin a la elaboracin de los patrones para evitar resultados inesperados. En los ejemplos incluimos comentarios relativos a algunos de esos resultados que, de no tenerlos previstos, pueden parecer desconcertantes.
Caso en los que la condicin es una retroreferencia Patrones de bsqueda Representan a Cdigo Ver fuente ejemplo Ver Todos estos ejemplos tienen marcado en rojo el condicional, dentro de l van la retro referencia, el Ver patrn que usar si se cumple la condicin y el patrn que usar si no se cumple la condicin. Ver Ver Los ejemplos anteriores sin incluir patrn para el caso en que no se cumple la condicin. Ver En los ejemplos se comenta lo relativo a los caracteres precedidos del smbolo \. Ver Ver Ahora hemos quitado a los ejemplos iniciales el patrn para el caso de que se cumpla la condicin. Ver Ver Ver Aqu hemos eliminado del condicional ambos patrones. Ver Ver Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar

([0-9]*)(?(1)[a-c]|[d-z]) (\"|\')(\<.*?)*(?(2)\\1|.*?\\1) ((a)|(b))(?(3) f| c) ([0-9]*)(?(1)[a-c]) (\"|\')(\<.*?)*(?(2)\\1) ((a)|(b))(?(3) f) ([0-9]*)(?(1)|[d-z]) (\"|\')(\<.*?)*(?(2)|.*?\\1) ((a)|(b))(?(3)| c) ([0-9]*)(?(1)) (\"|\')(\<.*?)*(?(2)) ((a)|(b))(?(3))
Caso en los que la condicin es el resultado de una comparacin de igualdad o desigualdad Patrn de bsqueda Representa a

Cdigo Ver fuente ejemplo Probar

(?(?<=[0-9][a-z])H|ms) (?(?<![0-9][a-z])H|ms) H(?(?=[0-9][a-z])|ms)

Si se cumple la condicin verde(un nmero delante de una letra) agrupa esa condicin a la H para conformar la palabra a buscar. Si no se cumple aquella condicin considera patrn de bsqueda Ver la palabra "ms" Si se cumple la condicin verde(un nmero delante de una letra) agrupa esa condicin a la H para conformar la palabra a buscar. Si no se cumple aquella condicin considera patrn de bsqueda Ver la palabra "ms" Si se cumple la condicin verde(un nmero delante de una letra) agrupa esa condicin a la H para conformar la palabra a buscar. Si no se cumple aquella condicin considera patrn de bsqueda Ver la palabra "ms"

Probar

Probar

Utilizando las opciones que nos ofrecen cada uno de los elementos que hemos ido viendo a lo largo de esta pgina podremos componer patrones de bsqueda que satisfagan casi todas nuestras necesidades. Es evidente que a medida que aumentemos los niveles de exigencia los patrones pueden ir adquiriendo una estructura bastante compleja. Veamos, en la pgina siguiente, los usos que podemos dar a los patrones en PHP.

Otras funciones con expresiones regulares


La funcin preg_match
Cuando se trata nicamente de conocer la existencia o inexistencia de texto dentro de una cadena o de un fichero puede resultar til la funcin: preg_match( patron, cadena, $coincidencias ) realiza una bsqueda en la cadena por medio de la expresin regular incluida en el patron. Si encuentra alguna coincidencia devuelve el valor booleano TRUE, en caso contrario devuelve FALSE.

El parmetro $coincidencias es opcional. Cuando se incluye recoger en un array con ese nombre los resultados de la bsqueda.

Informacin sobre variables Obtener informacin sobre variables


Veremos aqu algunas de las mltiples funciones que nos permiten obtener informacin sobre arrays y variables. sizeof(variable) La funcin sizeof devuelve el nmero de elementos de un array. Si se aplica sobre una variable (no array) devolver uno y tanto si se aplica sobre un array vaco, una variable con valor nulo o sobre una variable no definida, devolver cero. count(variable) Tiene idntica funcionalidad a la de sizeof.

<?php $a=array("Lunes","Martes","Miercoloes","Jueves", "Viernes","Sbado","Domingo"); $b=array( "Precio" => "17340 euros", "Color" => "Rojo", "Llantas" => "Aluminio"); $c=47; $d=""; $e=array(); echo "<h3>Valores usando sizeof()</h3>"; @print @print @print @print @print @print " " " " " " a b c d e f tiene: tiene: tiene: tiene: tiene: tiene: ".sizeof($a)." ".sizeof($b)." ".sizeof($c)." ".sizeof($d)." ".sizeof($e)." ".sizeof($f)." elementos<br>"; elementos<br>"; elementos<br>"; elementos<br>"; elementos<br>"; elementos<br>";

print "<h3>Valores usando count()</h3>"; @print " a tiene: ".count($a)." elementos<br>"; @print " b tiene: ".count($b)." elementos<br>"; @print " c tiene: ".count($c)." elementos<br>"; @print " d tiene: ".count($d)." elementos<br>"; @print " e tiene: ".count($e)." elementos<br>"; @print " f tiene: ".count($f)." elementos<br>"; ?>
ejemplo149.php

isset(variable) La funcin isset comprueba si una variable est definida. Si est definida incluso con valor nulo o como array vaco isset devolverUNO, en caso contrario devolver NUL. Esta funcin puede ser un complemento de sizeof o de count dado que permitira comprobar si estn definidas las variables en las que aquellas funciones devuelven dimensin cero. empty(variable) La funcin empty comprueba si una variable est vaca o no est definida. Si est vaca (valor nulo o array vaco) o no est definidaempty devolver UNO, en caso contrario devolver NUL.

Cuidado! No confundas isset con empty. No devuelven los mismos resultados. Mientras que isset slo comprueba si una variable est definida (tiene un valor aunque sea nulo) la funcin empty comprueba que la variable no est definida y, si lo est, que su valor sea nulo.
is_array(variable) Devuelve UNO (verdadero) en el caso de que la variable sea tipo array y NUL en el caso contrario. is_long(variable) o is_int(variable) o is_integer(variable) Estas tres funciones que son idnticas devuelven UNO en el caso de que la variable sea de tipo entero y NUL en el caso contrario. is_float(variable) o is_double(variable) Estas dos funciones tambin idnticas devuelven UNO en el caso de que la variable sea de tipo coma flotante y NUL en el caso contrario. is_string(variable) Devuelve UNO en el caso de que la variable sea tipo string y NUL en caso contrario. unset(variable) Destruye la variable indicada. Si despus de aplicar unset sobre una variable aplicamos de nuevo la funcin isset, nos devolver NUL indicando que ya no est definida. La funcin unset se puede aplicar tanto sobre variables como sobre un array y tambin sobre un elemento de un array.

<?php $a=array("Lunes","Martes","Miercoloes","Jueves", "Viernes","Sbado","Domingo"); $b=array( "Precio"=>"17340 euros", "Color" =>"Rojo", "Llantas" =>"Aluminio"); $c=47; $d=""; $e=array(); echo "<h3>Variables definidas</h3>"; echo echo echo echo echo echo " " " " " " Esta Esta Esta Esta Esta Esta definida definida definida definida definida definida la la la la la la variable variable variable variable variable variable a b c d e f ? ? ? ? ? ? ",isset($a),"<br>"; ",isset($b),"<br>"; ",isset($c),"<br>"; ",isset($d),"<br>"; ",isset($e),"<br>"; ",isset($f),"<br>";

echo "<h3>Identificacin de tipos de variables</h3>"; echo echo echo echo " " " " La La La La variable variable variable variable a a a a es es es es un array ? ",is_array($a),"<br>"; tipo double ? ",is_double($a),"<br>"; un entero ? ",is_int($a),"<br>"; un entero ? ",is_long($a),"<br>";

echo "<h3>Eliminando variables</h3>"; echo "La dimensin de a es: ",count($a),"<br>"; unset($a[0]); echo "Nueva dimensin de a: ",count($a),"<br>"; echo "La dimensin de b es: ",count($b),"<br>"; unset($b); @print "Nueva dimensin de b: ".count($b)."<br>"; echo " Sigue definida la variable b ? ",isset($b),"<br>"; print "<h1>Diferencias entre empty e isset</h1>"; print "<br />Cuando una variable no est definida ( \$sin_definir)<br /><br />"; print "El resultado de empty es (cero si no escribe nada): "; print empty($sin_definir); print "<br />El resultado de isset es (cero si no escribe nada): "; print isset($sin_definir); $soy_nula=""; print "<br /><br />Cuando una variable est definida con valor nulo ( \$soy_nula)<br />"; $definida; print "<br />El resultado de empty es (cero si no escribe nada): "; print empty($soy_nula); print "<br />El resultado de isset es (cero si no escribe nada): "; print isset($soy_nula); ?>
ejemplo150.php

Recuentos en arrays Recuento de los valores contenidos en una matriz


Algunas de las posibilidades de obtener informacin sobre los contenidos de un array son las siguientes: $recuento=array_count_values(array)

Con array_count_values la variable $recuento ser un nuevo array cuyos ndices son cada uno de los valores distintos que contengaarray y cuyos valores sern el resultado de contar el nmero de veces que se repite este nuevo ndice en el array inicial. Distingue entremaysculas y minsculas. Cuando los valores del array inicial (array) son nmeros enteros (sea array escalar o asociativo) $recuento ser unarray escalar. En caso contrario, ser asociativo.

Bsqueda de elementos en un array


claves=array_keys(array)

Devuelve un array escalar (claves) que contiene como valores los ndices del array inicial (array). claves=array_keys(array, valor)

Devuelve un array escalar (claves) que contiene como valores los ndices de los elementos del array inicial cuyo valor coincide con el indicado mediante el parmetro valor. valores=array_values(array) Esta funcin recoge en una nueva matriz (valores) todos los valores contenidos en el array. Es una forma de conversin de un array asociativo en otro escalar.

<?php $a=array(1,2,3,1,1,2,3,3,4,4,4,0,1); $b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul"); $c=array( "a"=>"rojo", "b" =>"verde", "c" =>"rojo", "d" =>"rojo", "e" =>"verde", "f" =>"Rojo", "g" =>"Verde"); echo "<h3>Cuenta valores del array()</h3>"; $contador=array_count_values($a); foreach($contador as $valor=>$veces){ echo "El valor ",$valor," se repite ", $veces," veces en la matriz a<br>"; } echo $contador[0],"<br>"; echo $contador[1],"<br>"; echo $contador[2],"<br>"; echo $contador[3],"<br>"; echo $contador[4],"<br>"; $contador1=array_count_values($b); foreach($contador1 as $valor=>$veces){ echo "El valor ",$valor," se repite ", $veces," veces en la matriz a<br>"; } echo $contador1["blanco"],"<br>"; echo $contador1["azul"],"<br>"; echo $contador1["Azul"],"<br>"; echo $contador1["Blanco"],"<br>"; $contador2=array_count_values($c); foreach($contador2 as $valor=>$veces){ echo "El valor ",$valor," se repite ",$veces," veces en la matriz a<br>"; } echo $contador2["rojo"],"<br>"; echo $contador2["Verde"],"<br>"; echo $contador2["verde"],"<br>"; echo $contador2["Rojo"],"<br>"; echo "<h3>Devuelve las claves de un array</h3>"; $claves=array_keys($a); foreach($claves as $v){ echo "El valor ",$v," es una de las claves<br>"; } $claves1=array_keys($a,1); foreach($claves1 as $v){ echo "El valor ",$v," es una de las claves de elementos de la matriz cuyo valor es <b>1</b><br>"; } echo "<h3>Devuelve los valores de un array</h3>"; $valores=array_values($c); foreach($valores as $v){ echo $v," Este es un de los valores de de la matriz c<br>"; } ?>
ejemplo151.php

Ordenacin de arrays (I)

Localizacin de valores en una matriz


in_array(valor,array)

La funcin in_array busca en la matriz (array) el valor (numrico o cadena) contenido en el parmetro valor. Si lo encuentra devuelve 1, y si no existiera devolvera NUL.

Posicionamientos en una matriz


Mediante estas funciones se puede modificar la posicin del puntero interno de una matriz y determinar los ndices de los elementos a los que apunta en cada momento. key(array)

Devuelve el ndice del elemento de la matriz al que apunta en ese momento el puntero interno de la matriz. reset(array)

Desplaza el puntero interno a la posicin del primer ndice del array. end(array)

Desplaza el puntero interno a la posicin del ltimo ndice del array. pos(array)

Mantiene el puntero interno en la posicin del actual. next(array)

Avanza el puntero interno en una posicin respecto a la actual. prev(array)

Retrocede el puntero interno en una posicin respecto a la actual.

Moviendo el puntero interno


<?php $a=array(1,2,3,1,1,2,3,3,4,4,4,0,1); $b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul"); $c=array( "a"=>"rojo", "b" =>"verde", "c" =>"rojo", "d" =>"rojo", "e" =>"verde", "f" =>"Rojo", "g" =>"Verde"); echo "<h3>Busca un valor en una matriz</h3>";

echo " Busca el valor en la "#</b> Si no ha puesto echo " Busca el valor en la "#</b> Si no ha puesto echo " Busca el valor en la "#</b> Si no ha puesto echo " Busca el valor en la "#</b> Si no ha puesto

matriz: nada no matriz: nada no matriz: nada no matriz: nada no

<b>#",in_array(3,$a), estaba, si 1 lo encontr <BR>"; <b>#",in_array(7,$a), estaba, si 1 lo encontr <BR>"; <b>#",in_array("gris",$b), estaba, si 1 lo encontr <BR>"; <b>#",in_array("blanco",$b), estaba, si 1 lo encontr <BR><br>";

echo "<h3>Posicionandose y determinando indices actuales</h3>"; echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo ?>
ejemplo152.php

"Este el valor asoaciado al indice 3 de la matriz a: ",$a[3],"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este es el valor siguiente al anterior: ",next($a),"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este es el primer valor de la matriz a: ",reset($a),"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este es el ultimo valor de la matriz a: ",end($a),"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este es el penltimo valor de la matriz a: ",prev($a),"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este es el mismo valor anterior: ",pos($a),"<br>"; "El puntero interno apunta a la clave: ",key($a),"<br>"; "Este el valor asoaciado al indice 4 de la matriz b: ",$b[4],"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>"; "Este es el valor siguiente al anterior: ",next($b),"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>"; "Este es el primer valor de la matriz a: ",reset($b),"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>"; "Este es el ultimo valor de la matriz a: ",end($b),"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>"; "Este es el penltimo valor de la matriz a: ",prev($b),"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>"; "Este es el mismo valor anterior: ",pos($b),"<br>"; "El puntero interno apunta a la clave: ",key($b),"<br>";

Ordenacin de arrays (II) Ordenaciones de arrays


Los elementos de un array se van ordenando segn se van definiendo. Por tanto, su orden no es el mismo que el de los valores de sus ndices. Las funciones PHP que ordenan los elementos de un array permiten dos opciones. Con una de ellas es posible la ordenacin de los elementos sin modificar los valores de los ndices, mientras que la otra s modifica los ndices. En el segundo de los casos la modificacin puede afectar incluso al tipo de ndices dado que los resultados de las ordenaciones tanto si hemos partido de un array escalar como si lo hemos hecho desde uno asociativo es siempre un array escalar.

Ordenacin por valores sin mantener ndices


sort(array)

Ordena los valores del array en sentido creciente y lo reindexa asignando ndice CERO al menor de los valores.

rsort(array)

Ordena la matriz en sentido decreciente de sus valores y la reindexa asignando ndice CERO al mayor de estos.

Ordenacin por ndices


ksort(array)

Ordena la matriz segn sus ndices y en sentido creciente de estos. krsort(array)

Ordena la matriz por ndices en sentido decreciente de los mismos.

Ordenacin por valores manteniendo ndices


asort(array)

Ordena la matriz segn sus valores en sentido creciente y mantiene los ndices del array original. arsort(array)

Ordena la matriz por valores en sentido decreciente y sigue manteniendo los ndices originales.

Ordenacin mediante funcin definida por usuario


PHP permite que el usuario pueda definir funciones en las que establezca sus criterios particulares de ordenacin. Las funciones PHP que permiten usar esta caracterstica son las siguientes: uasort(array, funcion)

Ordena la matriz utilizando los criterios establecidos por la funcin definida por el usuario y mantiene los ndices del array. usort(array, funcion)

Ordena la matriz por valores utilizando los criterios definidos en la funcin de usuario y modifica los ndices. uksort(array, funcion)

Ordena la matriz por claves utilizando los criterios definidos en la funcin. En el ejemplo hemos definido una funcin de comparacin siguiendo el criterio de ser o no ser mltiplo de 2. Trataremos lasfunciones en un tema aparte. La utilidad de la que hemos incluido en el ejemplo es la siguiente: Si el valor de la variable es par le asignamos un nmero negativo como respuesta y en caso contrario uno positivo. De esta forma los valores del array que devuelven negativos se consideran anteriores en la ordenacin a los que dan como resultado un nmero positivo.

<?php $a=array(1,2,3,1,1,2,3,3,4,4,4,0,1); $b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul"); $c=array( "b" =>"verde",

"c" =>"rojo", "e" =>"verde", "f" =>"Rojo", "g" =>"Verde", "a"=>"rojo", "d" =>"rojo",); sort ($a); echo "<h3>Ordenacin por valores usando sort</h3>"; foreach ($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } sort ($c); echo "<h3>Ordenacin por valores usando sort</h3>"; foreach ($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } rsort($a); echo "<h3>Ordenacin inversa por valores usando rsort</h3>"; foreach ($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } ksort($b); echo "<h3>Ordenacin por claves usando ksort</h3>"; foreach ($b as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } krsort($b); echo "<h3>Ordenacin inversa por claves usando krsort</h3>"; foreach ($b as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } asort($c); echo "<h3>Ordenacin por valores manteniendo indices </h3>"; foreach ($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } arsort($c); echo "<h3>Ordenacin inversa por valores manteniendo indices arsort</h3>"; foreach ($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } echo "<h3>Ordenacin por valores mediante funcin de usuario manteniendo indices</h3>";

/* esta funcin recoge el valor de la variable $a y aplicar el operador de comparacin ternario de forma que si el valor de la variable es impar devuelve como valor -2 y si es par devuelve 2 el 2 y el menos 2 nicamente establecen criterios de comparacin de modo que los valores -2 sern considerados anteriores a los valores +2 */ function micomparar (&$a) { return ($a%2!=0) ? -2 : 2; } uasort ($a, 'micomparar'); foreach ($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } echo "<h3>Ordenacin por clave mediante funcin de usuario </h3>"; uksort ($a, 'micomparar'); foreach ($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } echo "<h3>Ordenacin por valores mediante funcin de usuario </h3>"; usort ($a, 'micomparar'); foreach ($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor, "<br>"; } ?>
ejemplo153.php

Modificacin de arrays Modificaciones en arrays


var= range(inferior, superior)

Crea una nueva matriz escalar (var) en la que los valores de los elementos sern los nmeros enteros (ordenados) pertenecientes al intervalo comprendido entre los valores inferior y superior, incluidos estos. Tanto inferior como superior deben ser nmeros enteros. shuffle(array)

Intercambia de modo aleatorio los valores de un array y los reindexa. Igual que ocurra en el caso de los nmeros aleatorios, la funcinshuffle deber ir precedida de una semilla del tipo srand. En el ejemplo hemos usado como semilla la funcin: srand(time()).

var= array_flip(array)

Devuelve un array (var) que contiene como valores los ndices de la matriz array y como ndices los valores del propio array. Como quiera que los valores pueden estar repetidos y no es posible que lo estn los ndices, esta funcin, en caso de valores repetidos, toma cada uno de esos valores una sola vez, lo utiliza como ndice del nuevo array y asigna como valor del nuevo elemento el mayor de los ndices del array original de los elementos que contuvieran ese valor.

Insertando elementos en un arrays


array_unshift(arr, v1,v2,..)

Inserta al principio de la matriz arr los valores v1, v2, etctera que pueden ser tantos como se deseen y deben estar separados por comas. array_push(array, v1,v2,..)

Inserta al final de la matriz array los valores v1, v2, etctera, que igual que en el caso anterior, pueden ser tantos como se deseen y deben estar separados por comas. Tanto array_unshift como array_push asignan a los nuevos elementos ndices numricos. array_pad(array, n, var)

Inserta nuevos elementos en array y les asigna el valor contenido en var. Insertar tantos nuevos elementos como sea necesario para que el array alcance una longitud de n elementos. Si el valor de n es positivo inserta los elementos al final del array, si fuera negativo los insertara al comienzo del mismo. A los nuevos elementos del array se les asignan ndices numricos. array_merge($a, $b)

Crea un nuevo array escalar en el que se incluyen todos los elementos contenidos en los arrays $a y $b.

Quitar elementos de un array


array_shift($a)

La funcin array_shift extrae el primer elemento del array $a. array_pop($a)

La funcin array_pop extrae el ltimo elemento del array $a. array_slice($a,n)

La funcin array_slice extrae n elementos del array $a. Si el valor de n es positivo extraer todos los elementos a partir del que ocupa la posicin n contando desde el primero hasta el ltimo segn el orden de creacin de los elementos. Si el valor de n es negativo extraer todos los elementos a partir del ensimo, esta vez contando desde el ltimo hasta el primero. array_slice($a,n, m)

La funcin array_slice con dos parmetros permite extraer una parte de los valores de una matriz siguiendo estos criterios:

Si n y m son positivos, extraer m elementos a partir del que ocupa la posicin ensima de primero a ltimo. Cuando n es negativo y m es positivo se extraern m elementos contados a partir del ensimo, esta vez recorriendo el array deltimo a primero. En el caso en que n tenga valor positivo y m sea negativo extraer los comprendidos entre el ensimo contado de primero a ltimoy el emsimo contado desde el ltimo hasta el primero. Si n es negativo y m es tambin negativo extraer los caracteres comprendidos entre el ensimo contado de ltimo a primero y elemsimo contado en el mismo sentido. En este caso se requiere que el valor absoluto de n sea mayor que el de m. En caso de no cumplirse esta condicin devolver un array vaco.

Invertir el orden de un array


array_reverse(array)

Devuelve un nuevo array cuyos elementos estn en orden inverso al del array original. De esta forma el elemento que ocupaba la ltima posicin pasa a ocupar la primera y as sucesivamente.

Cuidado!
Recuerda que las posiciones iniciales de los elementos de un array no tienen relacin con sus ndices sino con la secuencia en la que fueron creados. Y otra cosa, mucho cuidado con la aplicacin de todas estas funciones y con los ndices de los arrays resultantes. Fjate en los ejemplos y vers que algunas estas funciones reindexan los resultados y los convierten en escalares an en el caso de que originalmente fueran asociativos. <?php $a=array(1,2,3,1,1,2,3,3,4,4,4,0,1); $b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul"); $c=array( "b" =>"verde", "c" =>"rojo", "e" =>"verde", "f" =>"Rojo", "g" =>"Verde", "a"=>"rojo", "d" =>"rojo"); $C=array( "b" =>"verde", "c" =>"rojo", "e" =>"verde", "f" =>"Rojo", "g" =>"Verde", "a"=>"rojo", "d" =>"rojo"); echo "<h3>Crea una matriz de nmeros enteros</h3>"; $r=range(7,11); foreach($r as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Intercambia aleatoriamente elementos en una matriz</h3>"; srand (time()); shuffle ($r);

foreach($r as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Intercambia valores e indices</h3>"; $p=array_flip($a); foreach($p as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; $q=array_flip($c); foreach($q as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Inserta elementos al principio de una matriz</h3>" array_unshift($a,97,"Pepe",128); foreach($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; array_unshift($c,97,"Pepe",128); foreach($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Inserta elementos al final de una matriz</h3>"; array_push($a,3.4,"Luis",69); foreach($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; array_push($c,3.4,"Luis",69); foreach($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Inserta elementos iguales al principio o al final de una matriz</h3>"; $wz1=array_pad($a,25,"relleno"); foreach($wz1 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; $wz2=array_pad($c,-17,"relleno"); ;

foreach($wz2 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Fusiona dos matrices</h3>"; $wz3=array_merge($a,$b); foreach($wz3 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Extrae el primer elemento de una matriz</h3>"; array_shift ($a); foreach($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; array_shift ($c); foreach($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Extrae el ultimo elemento de una matriz</h3>"; array_pop($a); foreach($a as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; array_pop ($c); foreach($c as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Extrae elementos de una matriz</h3>"; $zz1=array_slice($a,3); foreach($zz1 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; $zz2=array_slice($a,-3); foreach($zz2 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; $zz3=array_slice($b,3,4); foreach($zz3 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; }

echo "<br>"; $zz4=array_slice($b,3,-2); foreach($zz4 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<br>"; $zz5=array_slice($b,-5,-2); foreach($zz5 as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } echo "<h3>Invierte los elementos de la matriz</h3>"; $inv=array_reverse($C); foreach($inv as $clave=>$valor){ echo "Clave: ",$clave," Valor: ",$valor,"<br>"; } ?>
ejemplo154.php

Funciones de usuario Qu son las funciones de usuario?


De igual forma que lo hace el navegador en el caso del HTML, PHP lee e interpreta las instrucciones contenidas en los scripts de forma secuencial. Es decir, las instrucciones se van ejecutando en el mismo orden en el que aparecen en el documento original, con laexcepcin de las funciones ya que estas son bloques de instrucciones son puestos a disposicin de PHP que no se ejecutarn hasta el momento en que sean requeridas de forma expresa.

Dnde deben insertarse?


Aunque en versiones antiguas de PHP era necesario definir la funcin antes de invocarla, a partir de la versin 4 no es necesaria esa organizacin secuencial. La funcin pueden estar escrita dentro de cualquier script y en cualquier parte del documento, sin que tenga importancia alguna el lugar en el que se incluya la llamada a la misma. Tambin es posible y bastante habitual incluir funciones de uso frecuente en documentos externos de modo que pueden sercompartidas. En este caso, adems de invocarla es necesario indicar a PHP el lugar donde debe buscarla. Hablaremos de ello cuando estudiemos lo relativo a include.

Definicin de la funcin
Las funciones de usuario requieren la siguiente sintaxis: function nombre ( ) { ..... ... instrucciones ... ..... }

Es imprescindible respetar estrictamente la sintaxis que requiere de forma obligatoria los siguientes elementos:

La palabra function debe estar escrita en minsculas. El nombre de la funcin, que debe seguir criterios similares a los de los nombres de variables, aunque en este caso no se antepone el smbolo $ ni ningn otro. Los parntesis (), incluso cuando no contengan nada. Las llaves de apertura ({) y cierre (}) entre las que se escribirn las instrucciones correspondientes a la funcin.

Ejecucin de la funcin
Las funciones PHP no se ejecutan en tanto no sean invocadas. Para invocar una funcin la sintaxis es la siguiente: nombre()

Al ser llamada con esta sintaxis desde cualquier script se ejecutarn las instrucciones contenidas en ella. Con este primer ejemplo obtendremos una pgina en blanco. El script contiene una funcin pero no hay ninguna instruccin que la invoque y por lo tanto no se ejecutara.

<?php function a1(){ for($i=1;$i<=10;$i++){ echo $i,"<br>"; } } ?>


ejemplo155.php

<?php a1(); ?> <!-- Hemos escrito un script con una llamada a la funcin a1 que an no est definida. Tendremos que hacerlo, pero no importa la parte del documento en la que lo hagamos La pondremos en este nuevo script PHP //--> <?php function a1(){ for($i=1;$i<=10;$i++){ echo $i,"<br>"; } } ?>
ejemplo156.php

mbito de las variables


Resumamos lo ya comentado cuando tratamos el tema de las variables. Las funciones no leen valores de variables definidas fuera de su mbito salvo que dentro de la propia funcin se definan de forma expresa como globales. Si una funcin modifica el valor de una variable global, el nuevo valor persiste despus de abandonar la funcin.

Si dentro de una funcin se utiliza un nombre de variable idntico al de otra externa a ella (sin definirla global) la nueva variable se inicia con valor nulo y los eventuales valores que pudiera ir conteniendo se pierden en el momento en que se acaba su ejecucin.

<?php # definamos dos variables y asignmosles un valor $a=5; $b=47; # escribamos una funcin a1 y pidmosle que imprima sus valores function a1(){ @print "Este es el valor de $a en la funcin a1: ".$a."<br>"; @print "Este es el valor de $b en la funcin a1: ".$b."<br>"; } # hagamos una llamada a la funcin anterior # no nos escribir ningn valor porque esas variables no pertenecen # al mbito de la funcin y sern consideradas como vacas # en el mbito de la funcin a1(); # escribamos una nueva funcin, definamos como global $a # y comprobemos que ahora si la hemos incluido en el mbito # de la funcin function a2(){ global $a; @print "Este es el valor de $a en la funcin a2: ".$a."<br>"; @print "Este es el valor de $b en la funcin a2: ".$b."<br>"; } # invoquemos esta nueva funcin y veamos que ahora # si se visualiza el valor de $a pero no el de $b a2(); # creemos una nueva funcin y ahora modifiquemos dentro de ella # ambas variables function a3(){ global $a; $a +=45; @$b -=348; echo "Este es nuevo valor de $a en la funcin a3: ",$a,"<br>"; echo "Este es el valor de $b en la funcin a3: ",$b,"<br>"; } # invoquemos la funcin a3 a3(); # comprobemos -desde fuera del mbito de la funcin # que ocurri con los valores de las variables echo "El valor de $a HA CAMBIADO despues de ejecutar a3 es: ",$a,"<br>"; echo "El valor de $b NO HA CAMBIADO despues de ejecutar a3 es: ",$b,"<br>"; # probemos que ocurre con una variable superglobal # veremos que sin ser definida expresamente en a4 # si pertenece a su mbito y por lo tanto visualizamos su contenido function a4(){ print "La superglobales si estn: ".$_SERVER['SERVER_NAME']."<br>"; } # invoquemos esta nueva funcin a4(); ?>
ejemplo157.php

Asignacin de valores a variables


A las variables no globales se les pueden asignar sus valores iniciales de dos formas: Incluyndolas en una lnea de instrucciones contenida en la propia funcin.

Insertando los nombres de variable y sus valores dentro del parntesis que de forma obligatoria debe seguir al nombre de la funcin. En este ltimo caso la sintaxis sera: function nombre_funcion ($variable1=valor1,$variable2=valor2)

donde $variable1 y $variable2 son nombres de variables a utilizar en el mbito de la funcin y valor1 y valor2 los valores asignados a cada una de ellas. En este parntesis pueden incluirse separndolas con comas cuantas parejas variable = valor sean necesarias. Una forma alternativa a la anterior sera la siguiente: function nombre_funcion ($variable1,$variable2)

que requerira asignar los valores de cada una de la variables desde la llamada a la funcin, que ahora deber tener esta sintaxis: nombre (valor1, valor2,...);

y donde habra que escribir los valores separados por comas, y encerrados entre comillas cuando se trata de variables alfanumricas. Si el nmero de valores contenidos en la llamada fuera mayor que el nmero de variables definidas en la funcin, los excedentes seran ignorados y, si fuera inferior, se asignara valor nulo a las variables a las que no se transfiriera ningn valor. Tambin es posible incluir en la llamada a la funcin los nombres de algunas variables definidas en el mbito externo a la funcin. Se hara de la siguiente forma: nombre ($var1, $var2,...);

<?php $a=-13; $b=7482; $c="Ambrosio"; # esta es una forma alternativa de asignar valores a una variable # del mbito de la funcin function a1($a=56, $b=25){ echo "El valor de $$a en la funcin a1: ", $a,"<br>"; echo "El valor de $$b en la funcin a1: ", $b,"<br>"; } a1(); echo "El valor de $a despues de ejecutar la funcin es: ",$a,"<br><br>";

# Pasando valores desde la llamada a la funcin # /* Definamos una funcin fun1 e incluyamos dentro de su parntesis nombres de variables, separados por comas pero ahora sin asignarles ningn valor */ function fun1($x,$y,$z){ print "Valor de la variable x: ".$x."<br>"; print "Valor de la variable y: ".$y."<br>"; print "Valor de la variable z: ".$z."<br>"; }

# debemos hacer la llamada a la funcin pero ahora # lo haremos de forma distinta.

# Vamos a incluir en la llamada # los valores que queremos asignar a las variables de la funcin # Escribiremos dentro del parntesis de la llamada # los valores de cada una de las tres variables # separados por comas # (si se trata de una cadena, pongmosla entre comillas) # y veremos con la funcin recoge esos valores asignados #en la llamada fun1(14,"Robustiano",23.4); /* si esta llamada contuviera ms de tres valores los ltimos serian ignorados */ fun1(49.3,"Eustaquio",78,"Lupicio",456); # si contuviera menos de tres valores # PHP nos dara un mensaje de error # advirtiendo que falta un valor # pero nos devolvera los valores fun1("Desiderio","Bailador"); # esos mensajes de error podramos evitarlos # poniendo una arroba delante de la llamada a la funcin @fun1("Nuevo Desiderio","Nuevo Bailador"); # tambin podra utilizarse una sintaxis como esta # en la que dejamos en blanco (entre comillas) # el espacio correspondiente al segundo valor # aunque si incluimos las comas. # La variable que ocupa esa posicin # sera considerada como nula fun1("La luna",'',"verde"); # tambin podramos incluir en la llamada nombres de variables # definidas en el mbito general del sript # un este caso la funcin usaria esos valores fun1($a,$b,$c); ?>
ejemplo158.php

Pasar por referencia


Tal como hemos visto, las funciones PHP pueden recibir valores de variables externas y utilizar esos valores sin que el valor original de las mismas salvo que se les asigne la condicin de globales dentro de la funcin sufra modificacin. Una manera de lograr que los valores de una variable externa puedan ser modificados por una funcin, es lo que se llama en argot informtico pasar variables por referencia. La forma de hacerlo es esta: Hay que anteponer al nombre de la variable el smbolo & y PHP interpretar que la estamos pasando por referencia. El & puede anteponerse tanto en la definicin de la funcin como en la llamada a la funcin, tal como puedes ver en el ejemplo. La segunda de las opciones nos concede mayor libertad dado que permite usar una sola funcin y decidir en cada llamada la forma de pasar los parmetros.

<?php $a=3; $b=2; function a1($a,$b){

$a=pow($a,2); $b=pow($b,3); echo "El cuadrado de a dentro de la funcin es: ",$a, "<br>"; echo "El cubo de b dentro de la funcin es: ",$b, "<br><br>"; } a1($a,$b); echo "Al salir de la funcin a conserva la modificacin: ",$a, "<br>"; echo "Por el contrario, b no la conserva: ",$b, "<br><br>"; $c=8; $d=12; function b1($a,$b){ $a=pow($a,2); $b=pow($b,3); echo "El cuadrado de a dentro de la funcin es: ",$a, "<br>"; echo "El cubo de b dentro de la funcin es: ",$b, "<br><br>"; } b1(&$c,$d); echo "Al salir de la funcin c conserva la modificacin: ",$c, "<br>"; echo "Por el contrario, d no la conserva: ",$d, "<br><br>"; ?>

ejemplo159.php

Cuidado! Si tratas de ejecutar una funcin en la que colocas el & en la llamada a la funcin y te aparece un mensaje como este: Warning: Call-time pass-by-reference has been deprecated -argument passed by value; If you would like to pass it by reference, modify the declaration of function(). If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file. lo que estar ocurriendo es que php.ini tiene configurada en Off la directiva allow_call_time_pass_reference Eso suele ocurrir con algunos hostings y tambin con la configuracin por defecto de algunas versiones de PHP. A partir de la versin 5.3.3 este mensaje sustituye Warning por Deprecated con lo cual nos advierte de que se trata de un funcin que se queda obsoleta y que, probablemente, ser desactivida en versiones posteriores de PHP. La manera de evitar esa advertencia es no incluir en smbolo & en la llamada a la funcin.

Otra forma de definir funciones de usuario


Existe otra opcin de definicin de funciones de usuario que puede resultar de mucho inters. En este caso la funcin se define en tres bloques: Definicin de la funcin, llave de apertura { y cierre del script PHP (?>). Contenido de la funcin formado exclusivamente por cdigo HTML que ser incluido en el documento cuando sea invocada la funcin que lo contiene. Cierre de la funcin (llave de cierre }) contenido en un script PHP, es decir, entre las etiquetas de apertura (<?php) y cierre (?>) de un script de PHP. Cuando es invocada una funcin definida de esta forma puedes verlo en el ejemplo PHP se limita a escribir en el documento final los textos contenidos entre la etiqueta de apertura y cierre de la funcin. Las funciones de esta forma son particularmente tiles para la construccin de espacios web que contienen una serie de pginas en las que se repiten las mismas estructuras.

<?php function Encabezado() { ?> <!-- Hemos abierto la funcin y cerrado la etiqueta PHP todo esto es cdigo HTML //--> <html> <head> <title>Titulo de mi pgina</title></head> <body bgcolor="#FF0000"> <!-- Esta nueva llamada a PHP insertando la llave de cierre de la funcin indicar a PHP que debe escribir todo lo contenido entre la { y esta } //--> <?php } ?> <?php function Pie() { ?> <HR> </body> </html> <?php } ?> <!-- Utilizaremos esas dos funciones para crear una pgina web. Llamamos a la funcin Encabezado luego escribimos un texto y por ltimo insertamos el Pie de pgina con la funcin Pie //--> <?php Encabezado(); ?> Este es texto que aparecer en el cuerpo de la pgina. Est fuera de los scripts de php y ser considerado como un texto HTML. Debajo aparecer la lnea horizontal que insertaremos mediante una nueva llamada a la funcin Pie <?php Pie(); ?>
ejemplo160.php

Funciones que devuelven valores Funciones que devuelven valores


Las funciones PHP pueden ser llamadas a partir de un script y posteriormente recoger en ese mismo script los resultados de su ejecucin. Para conseguir este resultado debemos escribir dentro de la funcin la instruccin return seguida de la variable o la instruccin cuyo resultado queremos que sea devuelto al script desde el que ha sido llamada la funcin. Tal como podemos ver en el ejemplo, los valores devueltos por return pueden ser presentados directamente en la pgina o recogidos por una variable. Tambin es posible que la funcin genere un array y que este sea devuelto a una variable que se convertira a ese tipo de forma automtica. Otra opcin de recoger los valores devueltos por return es invocar la funcin mediante una llamada del tipo: list(v1, v2,..)=llamada

Las variables v1, v2, etc. recogern los valores de los elementos del array devuelto por la funcin.

<?php # asignamos valores a dos variables $a=3; $b=5; # escribimos una funcin que eleva la variable a # a la potencia indicada en b # insertando return delante de la operacin

function a1($a,$b){ return pow($a,$b); } #incluimos en la instruccin echo una llamada # a la funcin y en ella pasamos los valores # recogidos en las variables a y b # return conseguir que se ejecute esa funcin # y que echo recoja e imprima el resultado echo "El valor de a elevado a b es: ",a1($a,$b),"<br>"; # esta otra funcin generar y devolver un array # con los resultados de la ejecucion del bucle for function a2($a,$b){ for ($i=0;$i<=$b;$i++){ $z[]=pow($a,$i); } return $z; } # hacemos una llamada a la funcin $p=a2($a,$b); # leemos el array devuelto desde fuera de la funcin foreach($p as $clave=>$valor){ echo "El valor de a (3) elevado a: ",$clave," es: ",$valor,"<br>"; } echo "<br>"; # otra forma de leer el array con los resultados de la funcin list($r,$s,$t)=a2($a,$b); echo "Este es el valor recogido en la variable r :",$r,"<br>"; echo "Este es el valor recogido en la variable s :",$s,"<br>"; echo "Este es el valor recogido en la variable t :",$t,"<br>"; ?>
ejemplo161.php

Funciones de fecha Funciones de fecha


PHP es prdigo en cuanto a posibilidades de manejo de fechas y horas. Para ello, cuenta, entre otras, con las siguientes funciones: date (cadena de formato)

Devuelve valores de fecha y hora actuales utilizando los parmetros que se sealan en la tabla para establecer el formato de salida de los datos. Dentro de la misma cadena de formato puede contener tantos parmetros como se deseen. Parmetros de formato de date()
Valor Funcionalidad Sintaxis Resultado

A a d j F M m n

AM-PM am-pm Da del mes en formato de 2 dgitos da del mes sin ceros a la izquierda Nombre del mes (texto completo) Nombre del mes (3 letras) N del mes (de 01 a 12) con dos dgitos N del mes (de 1 a 12) sin dos dgitos

date("A") PM date("a") pm date("d") 06 date("j") 6

date("F") June date("M") Jun date("m") 06 date("n") 6

Y y G H g h i s l D w z t L Z U S

Ao con cuatro dgitos Ao con dos dgitos Hora 0-23 sin ceros a la izquierda Hora 0-23 con dos dgitos Hora 1-12 sin ceros a la izquierda Hora 01-12 con dos dgitos Minutos de 00 a 59 con dos dgitos Segundos de 00 a 59 con dos dgitos da semana en texto completo Da de la semana (tres letras)

date("Y") 2012 date("y") 12 date("G") 18 date("H") 18 date("g") 6 date("h") 06 date("i") 12

date("s") 38 date("l") Wednesday

date("D") Wed

da semana de 0 (domingo) a 6 (sabado) date("w") 3 das transcurridos del ao actual Nmero de das mes actual Ao actual bisiesto (1), no bisiesto (0) Diferencia (seg.) horaria local con GMT Segundos Unix Epoch Sufijo ordinal ingls date("z") 157 date("t") 30

date("L") 1 date("Z") 7200 date("U") 1338999158 date("S") th

Como puedes ver en este ejemplo, respeta los caracteres separadores (espacios, dos puntos, guiones, etctera) que se hubieran incluido en la cadena de formato siempre que no coincidan con ninguno de los parmetros PHP para esta cadena. <?php echo "Son las ", date("h : i : s")," y hoy es ", date("j-n-Y")?> devolvera: Son las 06 : 12 : 38 y hoy es 6-6-2012

Cuidado! No olvides que PHP se ejecuta en el servidor que suele estar en un ordenador remoto. Por lo tanto, fecha y hora locales se refieren al lugar donde est instalado el servidor y que en nuestro caso servidor y cliente coinciden en un mismo equipo y coincidirn la hora del sistema con la del servidor. Pero si alojaras esta pgina en un hosting australiano, PHP nos devolvera los valores con hora y fecha de lasantpodas.
date (formato, nmero)

Esta funcin nos devuelve la fecha y hora del tiempo Unix indicado en el parmetro nmero. Recuerda que ese nmero indicasegundos contados a partir de la 0:00:00 (GMT) del da 1 de Enero de 1970. Este script devolver la fecha y hora en la que el tiempo Unix era de 456.573.426 segundos. <?php echo "Fu a las ", date("h:i:s",456073426)," del ", date("j-n-Y",456073426) ?> devolvera: Fu a las 05 : 03 : 46 del 14-6-1984 gmdate(cadena formato)

Se comporta de forma idntica a date() con la nica diferencia de que devuelve la hora y fecha GMT. Si te fijas en el ejemplo habr una o dos horas de diferencia segn accedas a esta pgina en verano o invierno. La fecha actual en hora GMT (observa la diferencia horaria): <?php echo "Son las ", gmdate("h : i : s")," y hoy es ", gmdate("j-n-Y")?> devuelve: Son las 04 : 12 : 38 y hoy es 6-6-2012 gmdate (formato, nmero)

Los mismos comentarios que con el caso anterior. La nica diferencia es que devuelve hora GMT. La fecha y hora GMT coincidente con el tiempo Unix 456.073.426 es: <?php echo "Fu a las ", gmdate("h:i:s",456073426)," del ", gmdate("j-n-Y",456073426) ?> devolvera: Fu a las 03 : 03 : 46 del 206-1984 checkdate(mes,da,ao)

Comprueba si los valores de los parmetros mes estn dentro del rango permitido (de 1 a 12), si el parmetro da es un valor vlido para ese mes (considera aos bisiestos) y si el valor del ao pertenece al rango 0 a 32767. Devuelve VERDADERO si los valores corresponden a una fecha correcta y FALSO en el caso de que no ocurra as. Ejemplos de checkdate()
Mes Da Ao Sintaxis Devuelve

10 32 1987 Checkdate(10,32,1987) 10 31 1987 Checkdate(10,31,1987) 1 2 2 gettimeofday() 29 2000 Checkdate(2,29,2000) 29 2001 Checkdate(2,29,2001)


1

Esta funcin devuelve un array asociativo con los siguientes ndices: sec El valor asociado a este ndice del array recoge la hora actual (Unix Each) expresada en segundos usec El valor asociado a usec recoge la fraccin en microsegundos de hora actual (Unix Each) minuteswest Devuelve los minutos al Oeste de Greenwich dsttime Devuelve el tipo de correccin horaria segn horarios de verano/invierno. El valor UNO corresponde a horario de verano, el valor CERO al de invierno y MENOS UNO en el caso en que sea desconocido. Ejemplos de gettimeofday()
Sintaxis $z= gettimeofday(); echo $z; echo $z['sec']; echo $z[usec]; echo $z['dsttime']; Devuelve Array 1338999158 727356 1

echo $z['minuteswest'']; -120

getdate()

Devuelve un array asociativo con parmetros de la fecha actual. Los ndices de este array y sus valores son los que puedes ver en la tabla. Ejemplos de getdate()
Funcionalidad Devuelve un array asociativo Sintaxis $s=getdate(); Devuelve Array

echo $s; Este ndice devuelve los segundos de la hora actual echo $s['seconds'] 38 Este ndice devuelve los minutos de la hora actual Este ndice devuelve la hora de la hora actual Este ndice devuelve el da del mes actual Este ndice devuelve el n del da de la semana Este ndice devuelve el n del mes Este ndice devuelve el ao Este ndice devuelve n del da en el ao actual Este ndice devuelve el da de la semana Este ndice devuelve el nombre del mes echo $s['minutes'] 12 echo $s['hours'] echo $s['mday'] echo $s['wday'] echo $s['mon'] echo $s[year] echo $s['yday'] echo $s['month'] 18 6 3 6 2012 157 June

echo $s['weekday'] Wednesday

getdate(nmero)

Interpreta el nmero como una fecha Unix Each (segundos transcurridos desde el da 1 de Enero de 1970) y devuelve un array asociativo con los valores relativos a esa fecha. Los ndices de este array y sus valores son idnticos a los de getdate() tal como puedes ver en esta tabla. Ejemplos de getdate(nmero)
Funcionalidad Devuelve un array asociativo Sintaxis Devuelve $s=getdate(127648); Array echo $s; 28 27 12 2 5 1 1970 1 Friday January echo $s['minutes'] echo $s['hours'] echo $s['mday'] echo $s['wday'] echo $s['mon'] echo $s['year'] echo $s['yday'] echo $s['weekday'] echo $s['month']

Este ndice devuelve los segundos de la hora actual echo $s['seconds'] Este ndice devuelve los minutos de la hora actual Este ndice devuelve la hora de la hora actual Este ndice devuelve el da del mes actual Este ndice devuelve el n del da de la semana Este ndice devuelve el n del mes Este ndice devuelve el ao Este ndice devuelve n del da en el ao actual Este ndice devuelve el da de la semana Este ndice devuelve el nombre del mes

time()

Esta funcin devuelve la hora actual en segundos expresada en tiempo Unix. <?php print "Han transcurrido ".time(). " segundos desde las cero horas del da 01-01-1970";?> devolvera: Han transcurrido 1338999158 segundos desde desde las cero horas del da 01-01-1970 microtime()

Esta funcin devuelve una cadena formada la fraccin de microsegundos de la hora actual expresada en tiempo Unix seguida de un espacio y de los segundos del tiempo Unix. <?php print "Estamos en la fraccin ".microtime(). " de segundo de la hora actual";?> devolvera: Estamos en la fraccin 0.72747400 1338999158 de segundo de la hora actual mktime (hora, minuto, segundo, mes, da, ao)

Devuelve el tiempo Unix de la fecha pasada como parmetro a la funcin. Es fundamental mantener la secuencia de los datos. Si se omiten argumentos (slo pueden omitirse por la derecha) tomar los de la fecha actual.

Cuando el parmetro da es cero devuelve el ltimo da del mes anterior, pero si pasamos cero como parmetro de mes nos dar un error. Ejemplos de mktime()
H Min Sec Mes Da Ao Tiempo Unix Fecha

23 12 57 6 23 12 57 6 25 12 57 6 23 97 57 6

16 1973 109116777 23:12:57 16-Jun-1973 16 1973 109116777 23:12:57 16-Jun-1973 16 1973 109123977 01:12:57 17-Jun-1973 16 1973 109121877 00:37:57 17-Jun-1973 1973 128902377 23:12:57 31-Jan-1974

23 12 57 14 16 1973 130284777 23:12:57 16-Feb-1974 23 12 57 14 0

En los ejemplos de esta tabla puede verse cmo para valores fuera de rango (mes mayor de 12, minutos mayor de 60, etctera) la funcin realiza la correccin correspondiente.

Cuidado! En versiones anteriores a PHP 5.3.3 la funcin mktime inclua un sptimo parmetro (que se agregaba detrs de valor ao) relativo a horarios de verano invierno. Ese parmetro era 0 si la fecha corresponde a horario de invierno y 1 -1 (segn versiones) en el caso de horario de verano. Actualmente esa opcin es considerada obsoleta por PHP. Por esta razn no usamos ese sptimo parmetro en nuestros ejemplos.

Funciones de calendario Los distintos calendarios


Das julianos
El sistema de das julianos fue creado por Joseph Justus Scaliger en 1582 y fue llamado as en recuerdo de su padre, Julius Cesar Scaliger. Se trata de un sistema de cuenta de das que tiene su origen en el 1 de Enero del ao 4713 a.C. y que acabar el 31 de Diciembre de 3267. Este ciclo es producto de multiplicar tres ciclos menores: uno de 28 aos denominado solar, otro de 19 aos, que incorpora las fases lunares y uno de 15 aos denominado de indiccin. El da juliano es el nmero resultante de contar los das transcurridos desde la fecha definida por Scaliger como comienzo del ciclo.

Calendario juliano
El emperador romano Julio Cesar orden en el ao 44 a.C. la reforma del calendario. Sustituy el lunar adoptando, con modificaciones, uno solar de origen egipcio que data del 4000 a.C. Con la asesora de Sosgenes de Alejandra fij la duracin de cada ao en 365,25 das, insertando un da suplementario en febrero cada cuatro aos, -bis sextus dies ante calendas Martii(dos sextos das antes de las calendas de marzo), haciendo bisiestos a todos los aos cuyo nmero de orden sea divisible por cuatro.

Calendario gregoriano
A lo largo la Edad Media se sigui manteniendo en gran parte de Europa el calendario juliano con la nica adaptacin de fijar la fecha de referencia de la cuenta de aos en el nacimiento de Cristo. Pero dado que la duracin real del ciclo de translacin de la tierra alrededor del sol es de 365,2422 das solares medios, el calendario juliano con aos de 365,25 das empezaba a acumular un error importante. El Papa Gregorio XIII realiz la correccin en el ao 1582. Se descontaron diez das y es por eso que en 1582, al cuatro de octubre le sigui el da quince (viernes).

Para evitar sucesivos desfases se modificaron las condiciones de los aos bisiestos que, en lo sucesivo, habran de cumplir la condicin de que su ordinal sea divisible por 4 y que no acabe en 00 con la excepcin de los mltiplos de 400 que tendran condicin bisiestos.

Calendario judo
La era juda comienza a contar desde un supuesto ao de la creacin del mundo, que se calcula sumando las edades de las distintas generaciones mencionadas en la Biblia. El ao judo se corresponde con el cristiano sumndole a ste 3.760 aos. El ao judo es solar como el cristiano, pero sus meses son lunares, por lo que cada dos o tres aos tiene que aadirse un mes bisiesto para adecuar al ao solar el cmputo de los meses lunares.

Calendario republicano francs


El Calendario Republicano fue adoptado por la Convencin Francesa partiendo de las propuestas tcnicas formuladas por el matemtico Lagrange. Es un intento de adaptar el calendario al sistema decimal y eliminar referencias religiosas. El comienzo del ao coincida con el da 22 de Septiembre, equinoccio de otoo, y se fij su da uno del ao uno el 22 de Septiembre de 1792, da de la proclamacin de la Repblica. Consta 12 meses de 30 das, a los que se aaden cinco das complementarios (seis en los aos que son divisibles por 4 y no por 100) que son festivos y no se asignan a ningn mes. Los meses se dividen en tres dcadas de 10 das. El calendario fue de aplicacin civil en Francia y sus colonias americanas y africanas hasta 1806.

Funciones PHP para el manejo de calendarios


PHP dispone de una serie de funciones que permiten convertir fechas segn los distintos calendarios. Son estas: gregoriantojd(mes,da,ao)

Realiza la cuenta de das julianos correspondiente a la fecha gregoriana pasada en los parmetros mes, da y ao. El script <?php echo gregoriantojd (9, 27, 1999) ?> nos devolver: 2451449 que es el da juliano correspondiente a la fecha gregoriana:27 de setiembre de 1999. Este otro script <?php echo gregoriantojd (date("n"), date("j"), date("Y")) ?> nos devolver el da juliano correspondiente a la fecha actual. As que, para tu conocimiento y efectos pertinentes, hoy da 6 -6-2012 estamos celebrando el da juliano nmero 2456085. jdtogregorian(n de das julianos) Esta funcin devuelve en fecha gregoriana con formato: mes, da y ao el da juliano pasado como parmetro. Por si quieres ir preparando las celebraciones del 2.500.000 da juliano debes saber que coincidir con la fecha 8/31/2132 jdtojulian(n de das julianos) Con esta funcin puedes obtener la fecha juliana a partir de un valor de la Cuenta de Das Juliana . Este script <?php echo jdtojulian(gregoriantojd (date("n"), date("j"), date("Y"))) ?> nos devuelve la fecha actual segn el calendario julianoque es 5/24/2012 segn el calendario juliano. juliantojd(mes,da,ao) Convierte a Cuenta de das Julianos la fecha pasada (mes, da y ao) del calendario juliano. Por ejemplo <?php echo juliantojd(7,25,2011) ?> nos devolver 2455781 que corresponde a la cuenta de das correspondiente a la fecha 25/7/2001 expresada segn el calendario juliano. jdtojewish(n de das julianos)

Esta funcin nos devuelve la fecha (mes, da y ao) segn el calendario judo a partir de una fecha expresada en das julianos. <?php echo jdtojewish (gregoriantojd (date("n"), date("j"), date("Y"))) ?> nos dar la fecha actual segn el calendario judo que es: 10/16/5772. jewishtojd(mes,da,ao) Nos devuelve el da juliano correspondiente a una determinada fecha del calendario judo. Por ejemplo: <?php echo jdtogregorian(jewishtojd(7,21,5758)) ?> nos devolver 3/19/1998 que es la fecha gregoriana correspondiente al da 21 del sptimo mes del ao 5758 segn el calendario judo. jdtofrench(n de das julianos) Esta funcin nos devuelve la fecha segn el calendario republicano francs correspondiente al da juliano especificado como parmetro. <?php echo jdtofrench (gregoriantojd (5, 7, 1796)) ?> nos dar la fecha del calendario republicano francs que se corresponde con el 7 de Mayo de 1796 (gregoriano) que segn parece es: 8/18/4. Slo convierte fechas comprendidas entre los aos 1 y 14 (fechas Gregorianas del 22 de septiembre de 1792 al 22 de septiembre de 1806) que se corresponden con el perodo de vigencia oficial de este calendario. frenchtojd(mes,da,ao) Convierte una fecha del calendario republicano francs en su equivalente en das julianos. Por ejemplo: <?php echo jdtogregorian(frenchtojd(6,7,8)) ?> nos devolver 2/26/1800, que es la fecha gregoriana correspondiente al da 7 del sexto mes del ao 8segn el calendario republicano francs. Igual que la funcin anterior slo convierte fechas comprendidas entres los aos 1 y 14 del calendario francs. jdmonthname(da juliano, calendario) Devuelve del nombre del mes correspondiente al da juliano en el calendario sealado. Ejemplos de jdmonthname()
Fecha Gregoriano Juliano Gregoriano Juliano gregoriana abreviado abreviado 3/1/1803 3/2/1803 3/3/1803 3/4/1803 3/5/1803 3/6/1803 3/7/1803 3/8/1803 3/9/1803 Jan Feb Mar Apr May Jun Jul Aug Sep January February March April May June July August October Dec Jan Feb Mar Apr May Jun Jul Sep January February March April May June July August October Judo Republicano francs Nivose Pluviose Ventose Germinal Floreal Prairial Thermidor Fructidor Vendemiaire Frimaire

December Tevet Shevat AdarI Nisan Iyyar Sivan Av Elul

Tammuz Messidor

September Aug November Oct December Nov

3/10/1803 Oct 3/11/1803 Nov 3/12/1803 Dec Parmetro 0 calendario

September Tishri November Kislev

Heshvan Brumaire

Los parmetros sealados en la fila inferior son los correspondientes a los tipos de nombres de mes sealados en los encabezados de la tabla.

Da de Pascua
El Da de Pascua fue fijado en el Concilio de Nicea (ao 325) como el domingo siguiente a la primera luna llena posterior al equinoccio de Primavera. Este equinoccio se supone que siempre coincide con el 21 de marzo.

El algoritmo que usa PHP para su clculo se basa en el que desarroll Dionisio Exiguo en el ao 532. Para los aos anteriores a 1753, (calendario Juliano) usa un ciclo simple de 19 aos para calcular las fases de la luna. En los aos posteriores a esa fecha (Calendario Gregoriano) se aaden dos factores de correccin que tratan de hacer ese ciclo ms preciso. Mediante la funcin: easter_date(ao) Devuelve -en tiempo Unix- la media noche del da de Pascua del ao establecido como parmetro. Esta funcin slo es vlida cuando los valores del ao estn comprendidos entre 1970 y 2037 (tiempo UNIX). El script echo date( "j-n-Y", easter_date(2011)) nos seala que la Pascua del ao 2006 ha sido el da 24-4-2011. easter_days(ao) Devuelve el nmero de das del perodo comprendido entre el 21 de marzo y el da de Pascua. Si no se especifica el ao, se asume el actual. No tiene las limitaciones de la funcin anterior y es aplicable a aos fuera del intervalo de tiempo UNIX. El script easter_days(2011) nos seala que la Pascua del ao 2011 ha sido 34 das despus del 21 de Marzo.

Cuidado! Si piensas en la posibilidad de utilizar estas funciones en alguna aplicacin concreta que pretendas publicar en unhosting de la red cercirate antes de que estn habilitadas.

La opcin INCLUDE Utilizacin de ficheros externos


PHP dispone de funciones que permiten insertar en un documento una parte o la totalidad de los contenidos de otro. Esta opcin resulta muy interesante, tanto desde el punto de vista operativo como en lo relativo a la seguridad. Estos son algunos de los recursos que permiten ese tipo de inclusiones: include("nombre del fichero")

El parmetro nombre del fichero es una cadena que contiene el path y el nombre del fichero cuyos contenidos pretendemos incluir. Pueden incluirse ficheros con cualquier extensin aunque es muy habitual utilizar archivos con extensin .inc.php. La primera parte (inc) nos permitir identificar este tipo de ficheros mientras que la extensin php obligara a que (si un usuario malicioso pretende visualizar el contenido del fichero) fuera interpretado por PHP y, como consecuencia de ello, solo devolvera el resultado sin permitir la visualizacin de informaciones privadas (contraseas por ejemplo) que pudiera contener. Este primer ejemplo de fichero a incluir contiene nicamente texto y etiquetas HTML pero no contiene ninguna llamada a ninguna funcin PHP, ni tampoco ningn script de este lenguaje. Lo hemos guardado con dos extensiones: ejemplo1.inc.php y ejemplo1.inc. Si pulsas sobre las opciones Ver ejemplo podrs comprobar que los resultados de visualizacin son distintos dependiendo de la extensin de cada fichero.

<h3><font color="#ff0000">Este sera un texto que se incluira dentro de la pgina mediante las funciones include o require</font></h3><br>
Ver ejemplo1.inc Ver ejemplo1.inc.php

Este tipo de ficheros pueden contener: texto, etiquetas HTML y funciones. Si no contiene funciones se podr insertar tantas veces como se invoque y se insertar, adems, todo su contenido tal como puedes ver en el ejemplo.

Si el fichero contiene funciones solo podr ser invocado una vez ya que si se hiciera una segunda llamada se producira un error por duplicidad en los nombres de las funciones. Como vers en el ejemplo, es posible incluir cualquier tipo de funciones tanto las de la forma: <?php function nombre { ?> ..... ... cdigo HTML ... ...... <?php } ?>

con las que se pueden incluir porciones de cdigo HTML en cualquier script, como las del tipo: function nombre { ..... ... instrucciones PHP ... ...... }

que permiten invocar funciones repetitivas a partir de cualquier documento PHP.

<?php function Encabezado() { ?> <html> <head> <title> Pruebas con la funcin include </title> </head> <BODY> <center><img src="./images/cabina.jpg"><br> <font size=6 face="Times" color="#0000ff">Pruebas PHP</font><br> <hr width=75%> <?php } ?> <?php function Pie() { ?> <center><hr width=50%> <font size=2 face="Arial" color="#ff0000">Luchando con PHP</font> <hr width=50%></center> </body> </html> <?php } ?> <?php } ?>
Ver ejemplo2.inc Ver ejemplo2.inc.php

function Calcula($a,$b) { return $a*$b;

Definidas las funciones en el fichero a incluir y colocado al comienzo de la pgina un script que contenga el include y la ruta de ese fichero, bastar con invocar cualquiera de las funciones, en cualquier punto del documento, para que esa llamada sea sustituida por el resultado de la ejecucin de la funcin. Como es lgico, solo sern visualizados en el navegador del cliente los resultados de la ejecucin de las funciones que hayan sidoinvocadas.

<!-- empezaramos incluyendo el fichero que contiene las funciones. No escribira nada hasta que las funciones que contiene no fueran invocadas //-->

<?php include("ejemplo2.inc.php") ?> <!-- Insertaremos un script PHP que invoque la funcin encabezado. Debe llevar las etiquetas de apertura y cierre <?php y ?> de PHP //--> <?php Encabezado() ?> <!-- Insertaremos cdigo HTML segn nuestra conveniencia //--> Aqu ira el contenido de la pgina<br> .... esto es texto HTML................<br> ...........................<br><br><br> <!-- Incluimos el fichero ejemplo1.inc.php y dado que no contiene ninguna funcin, insertar aqu todo su contenidos //--> <?php include("ejemplo1.inc.php") ?> <!-- Insertaremos ms cdigo HTML --> ....................<br> ...........................<br><br><br> <!-- Incluimos nuevamente el fichero ejemplo1.inc.php Puede repetirse la inclusin porque no contiene funciones, si las contuviera habra un conflicto de duplicidad porque una funcion no puede estar definida dos veces con el mismo nombre. La instruccin include como en todos los casos deber ir dentro de un script PHP y por tanto entre <?php y ?> //--> <?php include("ejemplo1.inc.php") ?> <!-- Ahora ejecutaremos la funcion PHP Calcula() pasando como parmetros 7 y 9. El return de la funcin nos devolver el resultado que imprimiremos aqu //--> <?php print "Aqu va el resultado de la multiplicacin: ".Calcula(7,9); ?> <!-- Por ltimo invocaremos la funcin Pie() --> <?php Pie() ?>
Ver ejemplo162.php

La funcin require()
Tiene la misma sintaxis que include y una funcionalidad similar, aunque con algunas diferencias. Igual que ocurra con aqul, cuando un fichero es invocado por require esa llamada lo que hace es sustituirse a s misma por el contenido del fichero especificado. A diferencia de include, la etiqueta require lee y escribe en el documento a partir del que es invocada el archivo referenciado completo y no acepta condicionales que s son aceptados por include.

Evitar errores por duplicidad de llamadas


Tanto en el caso de usar la instruccin include como con require, si se intenta incluir dos o ms veces un fichero que contenga funciones, se producir un error (PHP no permite que dos funciones tengan el mismo nombre) y se interrumpir la ejecucin del script. Los errores de ese tipo pueden evitarse usando las funciones: include_once("fichero") y require_once("fichero")

que a diferencia de include y requiere van a impedir que un mismo fichero pueda incluirse dos veces. En los ejemplos vas a poder comprobar que no aparece el mensaje de error cuando se utiliza esta funcin y que el texto que anteriormente era incluido dos veces ahora solo aparece una vez.

<!-- Repetimos la inclusin de ambos ficheros pero veremos que no aparece mensaje de error por duplicidad de funciones y adems pese a hacer una doble insercin de ejemplo1 solo se visualiza una vez por efecto del filtro establecido por include_onde //--> <?php include_once("ejemplo2.inc.php") ?> <?php Encabezado() ?> Aqu ira el contenido de la pgina<br> ....................<br> ...........................<br><br><br> <?php include_once("ejemplo1.inc.php") ?> ....................<br> no aparecer nada aqu debajo<br><br><br> <?php include_once("ejemplo1.inc.php") ?> <?php include_once("ejemplo2.inc.php") ?>
Ver ejemplo163.php

El resultado de este otro ejemplo es idntico al anterior. Slo hemos sustituido include_once por require_once, que tiene una funcionalidad similar a la anterior.

<?php require_once("ejemplo2.inc.php") ?> <?php Encabezado() ?> Aqu ira el contenido de la pgina<br> ....................<br> ...........................<br><br><br> <?php require_once("ejemplo1.inc.php") ?> ....................<br> ....nada de aqu en adelante ...<br><br><br> <?php require_once("ejemplo2.inc.php") ?> <?php require_once("ejemplo1.inc.php") ?>
Ver ejemplo164.php

Comprobando los ficheros incluidos


PHP dispone de dos funciones que permiten recoger en un array la lista de ficheros que se han insertado en el documento por medio de alguna de las instrucciones: require_once, require, include_once e include. Tales funciones son estas: $v=get_included_files()

Recoge en un array escalar (contenido en la variable $v) los nombres de los ficheros incluidos en el archivo en uso por include_once. $v=get_required_files()

Igual que la funcin anterior recoge en un array escalar (contenido en la variable $v) los nombres de los ficheros incluidos en el archivo en uso mediante require_once.

<?php <?php <?php <?php

include_once("ejemplo2.inc.php") ?> Encabezado() ?> include_once("ejemplo1.inc.php") ?> Pie() ?>

Lista de fichero utilizados por include <?php $z= get_included_files(); foreach($z as $clave=>$valor) { echo "Clave: ",$clave," Valor: ",$valor,"<br>"; }; ?>
Ver ejemplo165.php

Mejorando la seguridad
Hemos hablado de la funcin show_source, que permita visualizar el cdigo fuente de los scripts no solo locales sino de cualquier URL- si esta funcin no estaba desactivada en el php.ini. Esa posibilidad de ver no slo permite el espionaje industrial (ver la tcnica de construccin de los scripts, etctera) sino que permite ver tambin las claves y contraseas de acceso a las bases de datos que pudieran contener los scripts. Aparte de simplificar el trabajo la opcin de incluir ficheros externos permite guardar la informacin confidencial fuera del root del servidor y usarla mediante estas llamadas. De ese modo show_source permitira visualizar el nombre de ese fichero externo pero no su contenido. Si creramos un directorio por ejemplo como subdirectorio de c:\Apache (fuera del root del servidor) y le ponemos como nombre sg, podramos guardar all los ficheros ejemplo2 y ejemplo1, con lo cual sus contenidos no seran visibles con show_source. En este caso la instruccin include ha de contener el path y sera la siguiente: include("C:\Apache\sg\fichero").

Cuidado! La manera de escribir los path difiere de un sistema operativo a otro. Bajo Windows debemos usar \ como separador, mientras que otros S.O. (Unix, Linux, etctera) requieren utilizar /. Para publicar tus pginas en un hosting no Windows tendras que modificar tus scripts. Tenlo en cuenta

Utilizando include para gestin de fechas


Las funciones que incluye PHP para el manejo de fechas solo contemplan periodos posteriores a 1970. Para el caso de fechas anteriores a esta, existen funciones que pueden descargarse desde: http://phplens.com/lens/dl/adodb-time.zip. El archivo comprimido contiene un fichero -adodb-time.inc.php- con funciones PHP que se comportan de forma idntica a las nativas de PHP y que, adems, permiten utilizar fechas anteriores a 1970 y valores negativos del tiempo Unix. Para utilizar estas funciones bastara con poner en el script include("adodb_time.inc.php"); y sustituir las funciones de fecha de acuerdo con lo que se indica en esta tabla:
Funcin PHP Funcin Adodb-time

getdate() date() gmdate() mktime()

adodb_getdate() adodb_date() adodb_gmdate() adodb_mktime()

En este enlace puedes comprobar los resultados de la aplicacin de estas funciones que, como vers, son idnticos a los que

hemos visto en el tema Funciones de fecha con la salvedad de que en este caso se admiten fechas anteriores a 1970 y tiempos Unix negativos.

Manejo de ficheros externos Utilizacin de ficheros externos


PHP dispone de funciones mediante las cuales se pueden crear, modificar, borrar y leer ficheros de cualquier tipo as como extraer informacin sobre ellos y sus contenidos.

Abrir o crear ficheros


Para crear o modificar ficheros se utiliza la instruccin: $f1=fopen(fichero,modo)

dnde $f1 es una variable que recoge el identificador del recurso, un valor importante (ser utilizado para referirnos a este fichero en instrucciones posteriores), fichero es el nombre (con extensin) del fichero a abrir o crear y deber escribirse entre comillas, y modo, que es una cadena que debemos poner entre comillas, el indicador del modo de apertura elegido. En la tabla hemos enumerado las opciones de ese parmetro. Valores del parmetro modo de la funcin fopen
Valor Funcionalidad

r r+ w w+ a a+

Abre el fichero en modo lectura y coloca el puntero al comienzo del fichero Abre el fichero en modo lectura y escritura y coloca el puntero al comienzo del fichero Abre el fichero en modo escritura y coloca el puntero al comienzo del fichero, reduce su tamao a cero y si el fichero no existe intenta crearlo Abre el fichero en modo lectura y escritura y coloca el puntero al comienzo del fichero, reduce su tamao a cero y si el fichero no existe intenta crearlo Abre el fichero en modo escritura y coloca el puntero al final del fichero y si no existe intenta crearlo Abre el fichero en modo lectura y escritura y coloca el puntero al final del fichero y si no existe intenta crearlo

Si el fichero que pretendemos abrir est en un directorio distinto al del script, debe incluirse el path completo delante del nombre del fichero y la cadena resultante debe ir entre comillas.

Cuidado! Si incluimos, junto con el nombre del fichero, un path hay que tener muy presente que bajo Windows hemos de utilizar siempre el separador anti-slash (\).

Cerrar ficheros
Una vez finalizado el uso de un fichero es necesario cerrarlo. Para ello PHP dispone de la siguiente intruccin: fclose($f1)

Esta funcin -que devuelve un valor booleano- permite cerrar el fichero especificado en $f1 que, como recordars, es el valor delidentificador de recurso que le fue asignado automaticamente por PHP en el momento de la apertura.

Punteros internos

PHP dispone de funciones para situar sus punteros internos y tambin para determinar la posicin a la que apuntan en un momento determinado. Se trata de las siguientes: feof($f1)

Es un operador booleano que devuelve CIERTO (1) si el puntero seala el final del fichero y FALSO si no lo hace. rewind($f1)

Coloca el puntero interno al comienzo del fichero indicado por el identificador del recurso $f1. fseek($f1, posicin)

Sita el apuntador del fichero sealado por el identificador del recurso $f1 en la posicin (expresada en bytes) sealada por posicin. ftell($f1)

Devuelve (expresada en bytes) la posicin actual del puntero interno del fichero.

Cuidado! Antes de utilizar funciones es necesario que el fichero que seala el identificador de recursos haya sido abierto.

Lectura de ficheros
La lectura de los contenidos de un fichero puede hacerse de dos maneras: sin apertura previa o con apertura previa del mismo.

Lectura de ficheros sin apertura previa


Las funciones que permiten la lectura de ficheros sin haber sido abiertos previamente son las siguientes: $t=file_get_contents(fichero)

Recoge en la variable $t el contenido del fichero cuyo nombre y eventual ruta se especifican en el parmetro fichero. readfile(fichero)

Escribe directamente en el punto de insercin del script el contenido completo del fichero.

Cuidado! La funcin readfile escribe el contenido del fichero sin necesidad de ir precedido por echo ni print. Si se pone echo o se recoge en una variable, adems de su contenido aadir un nmero que indica el tamao del fichero expresado en bytes.
$var=file(fichero)

Crea $var un array escalar cuyos elementos tienen como valores los contenidos de cada una de las lneas del fichero. Una lnea termina all donde se haya insertado un salto de lnea en el fichero original.

Lectura de ficheros con apertura previa


Para la utilizacin de estas funciones los ficheros han de ser abiertos en un modo que permita la lectura. fpassthru($f1)

Hace la lectura completa del fichero. Esta funcin presenta algunas peculiaridades importantes: Cierra el fichero de forma automtica despus de la lectura. Por esa razn, si se escribe la funcin fclose a continuacin defpassthru, se produce un error. Si el resultado se recoge en una variable, o si va precedido de echo, adems de escribir el contenido del mismo, aadir el nmero de bytes que indican su tamao. fgets($f1,long)

Extrae del fichero sealado por el $f1 una cadena que comienza en la posicin actual del puntero y cuya longitud est limitada por el menor de estos tres valores: El valor (en bytes) indicado en long. La distancia (tambin en bytes) desde la posicin actual del puntero hasta el final del fichero. La distancia que hay entre la posicin actual del puntero y el primer salto de lnea. fgetc($f1)

Extrae el caracter siguiente al sealado por la posicin actual del puntero.

Escribir en un fichero
Una vez abierto un fichero -en modo que permita escritura- la funcin PHP que nos permite escribir en el es la siguiente: fwrite($f1,"texto",long)

donde: $f1 sigue siendo el identificador de recurso, texto la cadena de texto a insertar en el fichero y long el nmero mximo de caracteres que han de insertarse. Si la cadena de texto tiene menor o igual longitud que el parmetro long la escribir en su totalidad, en caso contrario slo escribir el nmero de caracteres indicados. fputs($f1,"texto",long)

Es un alias de la funcin anterior. file_put_contents(nombre_fichero,$cadena)

Crea un fichero cuya ruta, nombre y extensin se definen mediante la cadena nombre_fichero e incluye en l el contenido de la variable$cadena. Esta funcin es idntica a llamar a fopen(), fwrite() y fclose() sucesivamente para escribir informacin en un archivo.

Cuidado! Estas funciones realizan la insercin de la cadena a partir de la posicin a la que apunte el puntero en el momento de ser invocadas. Si el fichero ya existiera y contuviera datos los nuevos datos se sobrescribiran sobre el contenido anterior. Para poder aadir contenidos a un fichero el puntero deber apuntar el final del fichero preexistente y estar abierto en un modo que permita aadir contenidos.

Borrado de ficheros
Para borrar ficheros se utiliza la siguiente instruccin: unlink(fichero)

Dnde fichero ha de ser una cadena que contenga el nombre y la extensin del fichero y, en su caso, tambin el path.

Duplicado de ficheros
La funcin: copy(fichero1, fichero2)

Copia el fichero fichero1 (debe indicarse nombre y extensin) en otro fichero cuyo nombre y extensin se establecen en la cadenafichero2. Esta funcin devuelve un valor booleano indicando si la copia se ha realizado con xito TRUE (1) o FALSE (nul) si por alguna razn no ha podido realizarse la copia.

Renombrar ficheros
La funcin: rename(fichero1, fichero2)

cambia el nombre del fichero fichero1 (hay que poner nombre y extensin) por el indicado en la cadena fichero2. Igual que la anterior, devuelve TRUE o FALSE. Si intentamos cambiar el nombre a un fichero inexistente nos dar error.

Funciones informativas
PHP dispone de funciones que nos facilitan informacin sobre ficheros. Algunas de ellas son las siguientes: file_exists(fichero)

Esta funcin devuelve TRUE si el fichero existe, en caso contrario devuelve FALSE. filesize(fichero)

Devuelve el tamao del fichero expresndolo en bytes. En caso de que el fichero no existiera nos dar un error. filetype(fichero)

Devuelve una cadena en la que se indica el tipo del fichero. En caso de que el fichero no existiera nos dar un error. filemtime(fichero)

Devuelve en tiempo Unix la fecha de la ltima modificacin del fichero. stat(fichero)

Devuelve un array que contiene informacin sobre el fichero. Hemos creado un fichero llamado domingo.txt para poder utilizarlo en los ejemplos. Su contenido es exactamente el siguiente (incluidos los saltos de lnea):

Esto es un ejemplo para comprobar si funcionan o no los saltos de lnea en un documento de texto que ser ledo desde php
En la tabla puedes ver los contenidos asociados a cada uno los ndices del array que contiene resultado de aplicar la funcin stat al fichero domingo.txt.
Indice Significado Dispositivo I node Modo de proteccin de I node Nmero de enlaces Id de usuario del propietario Id de grupo del propietario tipo de dispositivo si es un inode device Tamao en bytes Fecha del ltimo acceso Fecha de la ltima modificacin Fecha del ltimo cambio Tamao del bloque para el sistema I/O Nmero de bloques ocupados *
* * *

Sintaxis <? echo $d[0] ?> <? echo $d[1] ?> <? echo $d[2] ?> <? echo $d[3] ?> <? echo $d[4] ?> <? echo $d[5] ?> <? echo $d[6] ?> <? echo $d[7] ?> <? echo $d[8] ?> <? echo $d[9] ?> <? echo $d[10] ?> <? echo $d[11] ?> <? echo $d[12] ?>

Resultado

0 1 2 3 4 5 6 7 8 9 10 11 12

2056 28607187 33279 1 32031 32033 0 126 1338948639 1312376374 1312526279 4096 8

Los valores sealados con

devuelven -1 en algunos sistemas operativos, entre ellos Windows>

Otras funciones
Existen otras muchas funciones relacionadas con el manejo de ficheros y directorios, as como con los permisos de acceso, etctera. Hemos resumido nicamente las de mayor inters. Si quieres profundizar en este tema a travs de este enlace podrs acceder al captulo del Manual de Referencia oficial de PHP, en el que se describen las funciones relacionadas con el manejo de ficheros.

Ejemplos del uso de algunas funciones sobre ficheros


<?php /* abrimos con w+ con lo cual borramos el contenido y creamos el fichero en el caso de que no existiera */ $f1=fopen("sabado.txt","w+"); # escribimos en el fichero vaco fwrite($f1,"Esta es la primera linea que escribimos en el fichero<br>"); #cerramos el fichero fclose($f1); echo "<H2>Este es el resultado despus del primer fwrite</H2><br>"; include("sabado.txt"); # abrimos con r+ con lo cual sobreescribiremos # en el fichero preexistente $f1=fopen("sabado.txt","r+"); # escribimos en al principio del fichero preexistente # ya que al abrir un fichero en este modo el puntero # se sita al comienzo del fichero

fputs($f1,"Esto se sobreescribe"); #cerramos el fichero fclose($f1); echo "<H2>Este es el resultado despus del segundo fwrite</H2><br>"; include("sabado.txt"); # abrimos con a+ con lo cual AADIREMOS # al fichero preexistente ya que el modo de apertura # sita el puntero al final del fichero $f1=fopen("sabado.txt","a+"); # escribimos al final del fichero preexistente fputs($f1," Esto se aadir al final<br>"); #cerramos el fichero fclose($f1); echo "<H2>Este es el resultado despus del tercer fwrite</H2><br>"; include("sabado.txt"); echo "<h2>Leyendo con fgetc</h2><br>"; # abrimos con r+ con lo cual podemos LEER y AADIR # al fichero preexistente $f1=fopen("sabado.txt","r+"); # leemos el primer carcter del fichero # ya que el apuntador esta el principio $z=fgetc($f1); # imprimimos el primer carcter echo "He leido el primer carcter: ",$z,"<br>"; /* leemos el segundo caracter del fichero ya que el apuntador se ha movido a esa posicin al leer anteriormente el primer carcter. OBSERVA que NO HEMOS CERRADO AUN EL FICHERO */ $z=fgetc($f1); # este es el nuevo valor de la variable $z echo "He leido el segundo carcter: ",$z,"<br>"; /* leemos el siguiente caracter del fichero ya que el apuntador se ha movido a una nueva posicin Recuerda que NO HEMOS CERRADO AUN EL FICHERO */ $z=fgetc($f1); # este es ahora el valor de la variable $z echo "He leido el tercer carcter: ",$z,"<br>"; echo "<h2>Ahora el puntero est en el tercer caracter<br>"; echo "fgets empezar a leer a partir de el</H2>";; $z=fgets($f1,200); echo "Con fgets he leido esto: ",$z,"<br>"; #Ahora cerramos el fichero fclose($f1); echo "<br><H2>Al abrir el fichero de nuevo fgets comienza desde el principio</h2><br>"; #Abrimos de nuevo el fichero $f1=fopen("sabado.txt","r"); #Leemos su contenido $za=fgets($f1,5000); #Presentamos el contenido echo $za; #Ahora cerramos el fichero fclose($f1); echo "--------------------------------------------------------------<br>"; ?> <h2>Aqui veremos el contenido (sin etiquetas HTML)de una pagina web</H2> <?php # Escribimos la direccin completa de la pgina que puede ser # el resultado de unir el valor de la variable $_SERVER['DOCUMENT_ROOT'] # (ruta completa del directorio raz de servidor) # con el nombre del directorio que la contiene y nombre del fichero # la abrimos en modo solo lectura

$f1=fopen($_SERVER['DOCUMENT_ROOT']."/php/php24.php","r"); # Escribimos un bucle para que vaya leyendo # cada una de las lneas hasta llegar al final del fichero while (!feof($f1)) { $z = fgetss($f1, 1024); echo $z,"<br>"; } #Cerramos el fichero fclose($f1); #Borramos el fichero antes de salir unlink("sabado.txt"); ?>
Ver ejemplo166.php

Otro ejemplo completando el anterior


<?php # Abrimos el fichero en modo lectura $f1=fopen("domingo.txt","r"); # Al anteponer echo a fpassthru # NOS APARECER AL FINAL EL TAMAO DEL FICHERO echo fpassthru($f1),"<br>"; /* Abrimos de nuevo el fichero RECUERDA QUE FPASSHRU LO CIERRA AUTOMTICAMENTE DESPUS DE EJECUTAR LA INSTRUCCIN */ $f1=fopen("domingo.txt","r"); # Este bucle nos escribir cada una de las #lneas del fichero while(!feof($f1)){ $z=fgets($f1,4000); echo $z,"<br>"; } # Situamos el puntero #al comienzo del fichero rewind($f1); # Reescribimos el fichero while(!feof($f1)){ $z=fgets($f1,4000); echo $z,"<br>"; } # Situamos de nuevo el puntero #al comienzo del fichero rewind($f1); # Situamos el puntero #sealando el byte nmero 15 del fichero fseek($f1,15); # Releemos el fichero #ahora la primera lnea estar incompleta #LE FALTARN LOS 15 PRIMEROS CARACTERES while(!feof($f1)){ $z=fgets($f1,4000); echo $z,"<br>"; } # volvemos el puntero al comienzo del fichero rewind($f1); #leemos la primera lnea $z=fgets($f1,4000); echo $z,"<br>"; # Determinamos LA POSICIN ACTUAL DEL PUNTERO echo ftell($f1),"<br>";

# Cerramos el fichero fclose($f1); echo "_________________________________________<br>"; # leemos el fichero y lo presentamos # en diferentes modalidades $pepe=readfile("domingo.txt"); readfile("domingo.txt"); echo $pepe, "<br>"; #leemos el fichero y lo recogemos #en un array $z=file("domingo.txt"); #Al presentar la variable solo #nos aparecer la palabra array echo $z,"<br>"; # presentamos el contenido del array foreach($z as $linea=>$texto) { echo "Linea: ",$linea," Texto: ",$texto,"<br>"; }; # copiamos el fichero con mensaje de resultado if (!copy("domingo.txt", "otrodomingo.txt")) { print("Error en el proceso de copia<br>\n"); }else{ print "<br>Fichero copiado con exito"; } # renombramos un fichero con mensaje de resultado if (!rename("otrodomingo.txt", "otrolunes.txt")) { print("Error en el proceso de renombrado<br>"); }else{ print "<br>Fichero renombrado con exito"; } unlink("otrolunes.txt"); echo "Ultima modificacin a las: ",date("h:i:s A", filemtime ("domingo.txt"))," del da ", date("j-n-Y", filemtime ("domingo.txt")); echo "<br>El tamao del fichero es: ", filesize("domingo.txt")," bytes<br>"; echo "<br>El fichero es tipo: ", filetype("domingo.txt")," <br>"; echo "<br>Saldr un 1 si el fichero existe: ",file_exists("domingo.txt"); ?>
Ver ejemplo167.php

Ejemplo de un contador de visitas


<?php /* comprobamos si existe el fichero contador. Si existe leemos las visitas registradas e incrementamos su valor en una unidad Si no existe, registramos 1 como valor de nmero de visitas*/ if(file_exists("contador.txt")){ /* abrimos el fichero en modo lectura y escritura (r+) con lo que el puntero se colocar al comienzo del fichero */ $f1=fopen("contador.txt","r+"); # leemos el contenido del fichero $visitas=(int)(fgets($f1,10)); # lo aumentamos en una unidad $visitas++; # colocamos el puntero al comienzo del fichero para que # al guardar en nuevo valor sobreescriba el anterior rewind($f1); }else{ /*abrimos el fichero en modo lectura y escritura con (w+)

de modo que se cree automaticamente al no existir*/ $f1=fopen("contador.txt","w+"); #asignamos uno como valor a nmero de visitas $visitas=1; } /* escribimos el nmero de visitas en el fichero. En cualquiera de los casos el puntero estar al comienzo del fichero, por tanto cuando existan valores sern sobreescritos */ fwrite($f1,$visitas,10); print("Esta pgina ha sido visitada ".$visitas." veces"); fclose($f1); ?>
Ver contador

Guardar y leer datos transferidos mediante un formulario


Aunque el modo ms habitual de guardar informacin suele ser los servidores de bases de datos (MySQL, por ejemplo) la utilizacin de ficheros ofrece interesantes posibilidades de almacenamiento de informacin. Este es un ejemplo muy sencillo, en el que mediante un formulario tal como el que aparece en el recuadro puede transferirse y almacenarse la informacin en un fichero.

<form name="fichero" method="post" action="escribe.php"> <input type="text" name="nombre"> <input type="text" name="apellido"> <input type="edad" name="edad"> <input type="submit" value="enviar"> </form>
Los datos transferidos mediante un formulario como el anterior podran ser registrados y visualizados mediante un script como este:

<?php /*abrimos el fichero en modo a+ para permitir que se cree en caso de no existir, que permita los modos lectura y escritura y que escriba al final del fichero */ $f1=fopen("escribiente.txt","a+"); # hacemos un bucle para leer los valores transferidos # desde el formulario y recogidos en el array $_POST foreach($_POST as $v){ /* aadimos "\r\n" a cada valor para que se inserte un salto de lnea y que cada valor sea recogido en una lnea distinta en el fichero Limitamos las entradas a 150 caracteres*/ fwrite($f1,$v."\r\n",150); } /* para comprobar que los nuevos datos han sido agregados y visualizar el contenido ntegro del fichero situamos el puntero interno al comienzo del mismo */ rewind($f1); /* creamos un bucle que vaya leyendo todas las lneas hasta encontrar el final del fichero */ while (!feof($f1)) { /* vamos leyendo el contenido de cada lnea del fichero y aunque establecemos en 250 el nmero de carcteres dado que los saltos del lnea aparecern antes sern ellos los puntos de interrupcin de cada lectura*/ $z = fgets($f1,250); #presentamos el resultado de las lecturas echo $z,"<br>";

} # cerramos el fichero fclose($f1); ?>

Transferencia de ficheros Comprobacin de la configuracin


Antes de empezar con este tema debemos comprobar cul es la configuracin de nuestro php.ini. Si por alguna circunstancia los valores no coincidieran con los que tenemos aqu debajo, tendramos que abrir php.ini y modificar aquellas directivas. Cuando publicamos en un hosting no tenemos acceso al fichero de configuracin php.ini pero s podemos conocer su configuracin mediante el script info.php. Recordemos que ese fue nuestro primer script lo hemos creado y utilizado para comprobar nuestra instalacin y lo hemos guardado con ese nombre en el root de nuestro servidor /home/rinconas/public_html as que podremos acceder a l escribiendo como direccin http://localhost/info.php. La abundante lista que nos muestra info.php contiene las siguientes lneas (las podemos localizar fcilmente porque estn ordenadas alfabticamente), que en nuestro caso configuracin por defecto tendrn los valores que vemos en la imagen.

Es imprescindible que file_uploads=On (tal como aparece en la imagen) y resulta muy til tambin conocer el valor deupload_max_filesize que por defecto tal como ves en la imagen es de 2Mb. La primera directiva nos dice que PHP s permite subir ficheros al servidor y la segunda nos indica el tamao mximo (en Mbytes) de los ficheros que pueden ser objeto de esa transferencia. Si te apetece, y como simple experimento, podemos cambiar el lmite del tamao mximo de transferencia poniendo un valor ms reducido: upload_max_filesize=500K que nos servir para hacer alguna prueba sencilla.

Transferencia de ficheros
La transferencia de un fichero requiere dos documentos: un formulario que la inicie y un script que la recoja.

El formulario
Se diferencia del que hemos visto en pginas anteriores en tres aspectos. Dos de ellos se refieren a cambios dentro de la etiqueta<form> y el tercero es un nuevo tipo de input del que an no hemos hablado. En la etiqueta <form> hemos de incluir obligatoriamentemethod='POST' y ENCTYPE = "multipart/form-data" ya que no soporta ni otro mtodo ni otra forma de codificacin. El cuerpo del formulario ha de contener un nuevo tipo de input que utiliza la siguiente sintaxis: <input type='file' name='nombre'> Observa que en el formulario hemos insertado una variable oculta (hidden) con el fin de limitar el tamao mximo e impedir la transferencia de ficheros que excedan ese tamao.

<html> <body> <form enctype="multipart/form-data" action="ejemplo169.php" method="post"> # con este input "oculto" establecemos el lmite mximo

# del tamao del fichero a transferir. En este ejemplo 1.000.000 bytes <INPUT type="hidden" name="lim_tamano" value="1000000"> <p><b>Archivo a transferir<b><br> <input type="file" name="archivo"></p> <p><input type="submit" name="enviar" value="Aceptar"></p> </form> </body> </html>

La tranferencia
Una vez enviado el formulario, el fichero transferido se guarda en un directorio temporal del servidor salvo que php.ini especifique una cosa distinta con un nombre que le es asignado de forma automtica, y, adems, se recogern todos los datos relativos al contenido del fichero y a los resultados de la transferencia en la variable predefinida $_FILES. El la variable $_FILES tiene formato de array bidimensional. El primero de sus ndices es el nombre de variable usado para la transferencia (el especificado como name='nombre' en el input type='file'). Los segundos ndices se trata de un array asociativo tiene como valores: name, type, tmp_name, error y size. En ellos se recogen: el nombre original del fichero transferido, su formato, el nombre con el que ha sido guardado en el directorio temporal, el tipo de error de transferencia y el tamao del archivo. El error puede ser CERO o UNO. Si es CERO indica que la transferencia se ha realizado con xito. En caso contrario, el valor de ese error es UNO. Este script, al que hemos llamado ejemplo169.php es el que recoge la action de formulario que hemos incluido unas lneas ms arriba.

<?php /* Mediante el bucle foreach leemos el array $_FILES. Observa la sintaxis. Escribimos como nombre del array $_['archivo'] con lo cual foreach leer los elementos del array que tienen 'archivo" como primer ndice (coincide con el name que hemos puesto en la etiqueta input=file del formulario) */ foreach ($_FILES['archivo'] as $indice=>$valor){ print $indice."--->".$valor."<br>"; } /*Dependiendo del navegador que ests utilizando puede ocurrir que varan los valores del ndice type sean distintos. Cuando se trata de un fichero jpg, con IE devolver image/pjpeg, mientras que con Mozilla, Firefox, Opera y Netscape devolver image/jpeg.*/ ?>
ejemplo168.php

Enva un fichero cualquiera de menos de 2Mb y vers que el error es 0. Repite el envo, ahora con un fichero que sobrepase ese tamao, y comprobars que el error toma valor 1 dado que la directiva upload_max_filesize=2M del fichero php.ini habr bloqueado la transferencia. Puedes modificar la configuracin de php.ini y modificar esos lmites de transferencia. Al hacerlo incrementars o reducirs el lmite mximo de transferencia.

Copia del fichero


Tal como hemos visto, el fichero transferido an no est en el servidor. Por el momento se encuentra en un directorio temporal y ser preciso hacer una copia en nuestro espacio de servidor. Para este proceso puede utilizarse una funcin que ya hemos visto en pginas anteriores:

copy(fichero1, fichero2)

donde fichero1 sera el fichero temporal y fichero2 el del nuevo fichero. El primero de los nombres es el valor contenido en:$_FILES['nm']['tmp_name'] donde nm es el valor incluido como name en el formulario usado para la transferencia y tmp_name es unapalabra reservada que debe escribirse exactamente con esa sintaxis. El valor fichero2 podra ser un nombre cualquiera asignado en el propio script podemos verlo en el ejemplo o el nombre original del fichero transferido. En este caso habra que recogerlo del elemento del array anterior cuyo segundo ndice es name. En la cadena fichero2 podra incluirse recuerda que debes ponerlo entre comillas un path sealando el directorio o subdirectorio donde queremos que guarde la copia. De no incluirlo, el fichero se copiara en el directorio desde el que se est ejecutando el script.

Sintaxis alternativa
La opcin anterior tiene una alternativa, igual de eficiente y mucho ms segura. Se trata de: move_uploaded_file(fich1, fich2)

que tiene la misma utilidad que copy y aade algunas ventajas tales como: Comprobar que el fichero ha sido transferido mediante el mtodo POST e impedir que se copie en el servidor en caso de no cumplirse esa condicin. Si la opcin safe mode=on (configuracin de php.ini en modo seguro) por defecto est Off comprueba, adems, que la transferencia del fichero ha sido realizada por el mismo usuario que hace la peticin de ejecucin del script, evitando que alguien,maliciosamente, pueda mover ficheros desde el directorio temporal hasta el espacio de servidor. A diferencia de la anterior esta funcin mueve el fichero y por lo tanto no queda copia del mismo en el fichero temporal

Cuidado! Al usar esta funcin bajo Windows conviene indicar en el parmetro fichero2 la ruta absoluta completa junto con el nombre del fichero ya que de no hacerlo as en algunas ocasiones la imagen no ser transferida al directorio desde el que se ejecuta el script.

Mejorando las trasnferencias


Cuando est habilitada la opcin de transferencias de ficheros es conveniente en previsin de sorpresas desagradables tomar algunas cautelas. Una de ellas sera limitar la posibilidad de transferencia a determinados tipos de archivos imgenes, por ejemplo impidiendo con ello que pudieran transferirse al servidor ficheros de riesgo, tales como: ejecutables, virus, etctera. Cuando se establece este tipo de limitaciones, PHP comprueba los contenidos de los ficheros sin tomar en consideracin la extensin de los mismos. Con ello se evita el riesgo de que puedan esconderse cambiando la extensin ficheros distintos de los permitidos. Aqu tienes un ejemplo de script que impide la transferencia de ficheros con extensin distinta a .jpg o .gif.

<?php /* filtramos el tipo de archivos recibidos de forma que solo se permitan imagenes en formato jpg gif. Si el fichero transferido tuviera formato distinto, la funcin exit() acabara la ejecucin del script */ if(!($_FILES['archivo']['type']=="image/pjpeg" OR $_FILES['archivo']['type']=="image/jpeg" OR $_FILES['archivo']['type']=="image/gif")){ print "El formato ".$FILES['archivo']['type'].

" no est permitido"; exit(); }else{ # anidamos este segundo condicional # para guardar en una variable # la extensin real del fichero # mas adelante la utilizaremos if ($_FILES['archivo']['type']=="image/pjpeg" OR $_FILES['archivo']['type']=="image/jpeg" ){ $extension=".jpg"; }else{ $extension=".gif"; } } /* filtremos ahora el tamao de modo que no supere el mximo establecido en el hidden del formulario (lgicamente ese valor no puede superar el valor mximo de la configuracin de php, pero si puede ser menor) y tambin evitaremos archivos sin contenido, es decir con tamao CERO */ if($_FILES['archivo']['size']>$_POST['lim_tamano'] OR $_FILES['archivo']['size']==0){ print "El tamao ".$FILES['archivo']['size']." excede el lmite"; exit(); } # # # # # # asignemos un nombre a la imagen transferida de modo que se guarde en el servidor con un nombre distinto, asignado por nosotros con ello, podemos evitar duplicidades de nombres ya que si existiera un fichero con el mismo nombre que el enviado por el cliente, se sobreescribira

$nuevo_nombre="foto_abuelita"; # aadmosle la extensin real de fichero que tenamos # recogida en la variable nuevo_nombre $nuevo_nombre .=$extension; # aceptemos la transferencia siempre que el archivo tenga nombre if ($_FILES['archivo']['tmp_name'] != "none" ){ /* con la funcin copy pasaremos el archivo que est en el directorio temporal al subdirectorio que contiene el script que estamos ejecutando. Podramos incluir un path y copiarlo a otro directorio */ if (copy($_FILES['archivo']['tmp_name'], $nuevo_nombre)) { echo "<h2>Se ha transferido el archivo</h2>"; } }else{ echo "<h2>No ha podido transferirse el fichero</h2>"; } ?>

Funciones de compresin Herramientas de compresin


Existen varias herramientas para compresin de ficheros. Las ms populares son las funciones de la biblioteca bzip2 de Julian Seward que generan ficheros comprimidos que se reconocen por su extensin (bz2) y la funcin de zlib de Jean-loup Gailly y Mark Adler para leer y grabar archivos comprimidos con extensin gz. En esta pgina veremos el uso

de la segunda de las opciones. Empezaremos comprobando en info.php que la opcin est activada. Deberemos ver algo como esto:

En la versin de PHP que estamos utilizando esta opcin se activa por defecto y no es necesario modificar ningn parmetro enphp.ini.

Funciones zlib para compresin de ficheros


Algunas de esas funciones son estas: $f=gzopen(fichero,modo, ruta)

Abre el fichero identificado por el parmetro fichero y lo hace en el modo especificado en el parmetro modo (r o w segn se trate de modo lectura o escritura). Cuando se trata del modo de escritura el parmetro w debe ir seguido de un nmero comprendido entre cero ynueve que especifica el grado de compresin pretendido. El parmetro ruta es opcional y puede contener un valor lgico (cero uno). Cuando el valor de este parmetro es 1 permite incluir en el parmetro fichero la ruta del directorio o subdirectorio que alberga el fichero que tratamos de abrir. Si se incluye un path sin especificar el valor 1 en el parmetro ruta aparecer un error. gzclose($f)

Cierra el fichero asociado al identificador de recurso $f. Esta funcin devuelve TRUE en caso de xito o FALSE si se produjera un error. gzeof($f)

Esta funcin devuelve 1 (TRUE) en el caso de que el puntero apunte al final del fichero abierto e identificado mediante $f. Tambin devuelve TRUE en caso de error. Si el fichero estuviera abierto y el puntero apunta a una posicin distinta del final del fichero devolver FALSE. gzseek($f,desplaza)

Desplaza dentro del fichero identificado por $f el puntero a partir de su posicin actual la cantidad de bytes indicados en el parmetro desplaza. gztell($f)

Devuelve la posicin actual del puntero.

gzrewind($f)

Coloca el puntero al comienzo del fichero gzread($f, longitud)

Devuelve una cadena -despus de descomprimida- de longitud igual a la indicada en el parmetro longitud. La lectura comienza en laposicin actual del puntero y acaba cuando la longitud de la cadena leda y descomprimida sea igual al valor del parmetro longitud o cuando se haya alcanzado el final del fichero. gzpassthru ($f)

Esta funcin escribe en la salida (no necesita la funcin echo) el contenido del fichero desde la posicin actual del puntero hasta el final del fichero. Como es lgico, si estuviera precedida de gzrewind escribira el fichero completo.

Cuidado! La funcin gzpassthru cierra automticamente el fichero despus de escribir su contenido. Si pones gzclose despus de esta funcin te dar error y si quieres seguir utilizando el fichero tendrs que volver a abrirlo con la funcin gzopen.
gzwrite($f, cadena, long)

Esta funcin escribe en el fichero comprimido que se identifica por $f la cadena contenida en el parmetro cadena. Opcionalmente puede llevar el tercer parmetro (longitud) en cuyo caso solo escribir los primeros longitud bytes de la cadena. Si el parmetro longitudexiste y es mayor que la longitud de la cadena, insertar la cadena completa. gzputs($f, cadena, longitud)

Esta funcin es idntica a gzwrite. readgzfile($fichero,path)

Esta funcin abre de forma automtica el fichero indicado como parmetro fichero, adems lo lee y lo escribe de forma automticasin necesidad de usar echo ni ninguna otra funcin de salida. Si el fichero no est en el mismo directorio que el script -adems de incluir la ruta en la cadena fichero- es necesario aadir el segundo parmetro -path- con valor 1.

Ejemplo de compresin y lectura de un fichero


En este ejemplo trataremos de utilizar las funciones de compresin comentadas al margen. Si observas las formas de apertura de los ficheros vers que son similares a las utilizadas para la gestin de ficheros. Los modos de apertura para escritura son: "w0" a "w9" siendo los valores de cero a nueve los indicadores de los niveles de compresin. Para lectura debe usarse el modo "r" sin indicar ningn nivel de compresin.

<?php # asignamos un nombre al fichero con extensin "gz" $fichero ='prueba.gz'; # abrimos el fichero en modo escritura (w) # con el nivel mximo de compresin (9) $f=gzopen($fichero,"w9",0); $cadena="Este es el primer bloque de texto que hemos introducido en el fichero comprimido. "; $cadena .="Aadimos este segundo bloque"; echo "<i>Esta es la cadena inicial:</i> ".$cadena."<br>";

# escribimos (comprimida) la cadena en el fichero gzwrite($f,$cadena); # cerramos el fichero gzclose($f); #abrimos el fichero en modo lectura $f=gzopen($fichero,"r"); echo "<i>Estos son los tres primeros caracteres de la cadena:</i> "; # escribimos los tres primeros caracteres, el puntero (por defecto) # apunta al comienzo de la cadena echo gzread($f, 3)."<br>"; # desplazamos el puntero hasta el carcter n 8 gzseek($f,8); echo "<i>Estos son los seis caracteres siguientes al octavo:</i> "; # escribimos seis caracteres a partir del octavo echo gzread($f, 6)."<br>"; echo "<i>Ahora el puntero est en:</i> "; # buscamos la posicin actual de puntero echo gztell($f)."<br>"; # movemos el puntero hasta el comienzo del fichero gzrewind($f); echo "<i>Estos son los diez primeros caracteres de la cadena:</i> "; # escribimos los diez primeros caracteres del fichero echo gzread($f, 10)."<br>"; # volvemos el puntero al comienzo del fichero gzrewind($f); echo "<i>Escribimos el fichero completo:</i> "; # con gzpasthru escribimos el fichero completo # el puntero est al principio porque all lo ha situado gzrewind # no necesitamos utilizar "echo" ni "print" ya que gzpassthru # escribe directamente el contenido del fichero gzpassthru($f); # tenemos que volver a abrir el fichero ya que gzpassthru # se encarg de cerrarlo despus de leerlo $f=gzopen($fichero,"r"); echo "<br><i>Aqu estar todo el fichero:</i> "; gzpassthru ($f); # la funcin readgzfile abre el fichero, imprime su contenido y lo cierra echo "<br><i>Aqui se imprime la cadena completa usando readgzfile</i>: <br>"; readgzfile($fichero); /* con gzfile tambin se abre el fichero, pero ahora el contenido no se presenta directamente. Es recogido en un array. Para visualizarlo debemos imprimir el primer elemento del array. */ $z=gzfile($fichero); echo "<br><i>Este es el primer elemento (0) del array generado por gzfile</i>: ".$z[0]; # gzfile cierra el fichero. # No podemos poner gzclose porque nos dara error ?>
ejemplo174.php

Utilizando un directorio distinto


El ejemplo anterior est desarrollado para el supuesto que el script y el fichero comprimido estn en el mismo directorio. Si quieres utilizar estas funciones utilizando ficheros alojados en un directorio distinto, solo tendrs que recordar que algunas funciones deben incluir el parmetro complementario 1.- Estos son las modificaciones que deberas efectuar: La variable que recoge el nombre del fichero debe incluir el path, por ejemplo: $fichero ='/subdirectorio/prueba.gz'

La funcin gzopen debe incluir el tercer parmetro (path) con valor 1, por ejemplo: $f=gzopen($fichero,"r",1); Tambin las funciones gzfile y readgzfile -que abren automticamente el fichero- debern incluir ese valor 1 como parmetro aadido. Por ejemplo: readgzfile($fichero,1) $z=gzfile($fichero,1)

Eleccin del grado ptimo de compresin


Puede parecer que la condicin ptima de compresin sera elegir el nivel 9 y eso es cierto si tomamos nicamente en consideracin el tamao final del fichero comprimido. Sin embargo no existe una relacin lineal entre reduccin de tamao/nivel de compresin. Sin que pueda considerarse ninguna referencia exacta la compresin alcanzable depende del contenido del fichero y en consecuencia no puede establecerse una relacin funcional puede comprobarse experimentalmente que -aparentemente- a partir del grado 2 la reduccin de tamao del fichero es mnima y que cuando se aumenta el grado de compresin a niveles mximos (tratndose de ficheros de un cierto tamao) el tiempo de ejecucin aumenta sustancialmente como consecuencia de la reiteracin de la ejecucin de los algoritmos de compresin.

Comprimiendo cadenas
Las funciones anteriores permiten la creacin, lectura y modificacin de ficheros comprimidos. Sin embargo, existen otras funciones PHP que permiten comprimir cadenas. Aqu tienes algunas de ellas. gzcompress(cadena, nivel)

Esta funcin devuelve una cadena comprimida a partir de una original especificada en el parmetro cadena. El nivel de compresin (valores entre 0 y 9) se especifica en el parmetro nivel. Las cadenas resultantes de esta funcin pueden descomprimirse aplicando la funcin gzuncompress que referimos ms abajo. gzdeflate(cadena, nivel)

Se comporta de forma idntica a la funcin anterior. La nica salvedad parece ser que utiliza un algoritmo de compresin distinto. Las cadenas resultantes de esta funcin tambin pueden descomprimirse aplicando la funcin gzdeflate. gzencode(cadena, nivel, opciones)

Esta funcin devuelve la cadena cadena comprimida con el nivel especificado en nivel y permite dos opciones de compresin:FORCE_GZIP FORCE_DEFLATE que se pueden especificarse como tercer parmetro (opciones) sin encerrar entre comillas. El valor por defecto (cuando no se especifica el parmetro opcin) es FORCE_GZIP.

Descomprimiendo cadenas
gzuncompress(cadena)

Con esta funcin se obtiene la cadena original a partir de la cadena comprimida indicada en el parmetro cadena siempre que esta hubiera sido comprimida usando la funcin gzcompress. gzinflate(cadena)

Funciona igual que la anterior. La nica diferencia es que esta descomprime las cadenas que han sido comprimidas con gzdeflate.

Ejemplo de compresin y descompresin de cadenas


En este ejemplo utilizamos las tres funciones de compresin de cadenas as como las opciones de descompresin y lectura de cada una de ellas.

<?php # creamos una cadena de ejemplo $cadena="Esta es la cadena a comprimir. Intentaremos que sea larga porque parece que si la hacemos muy corta en vez de reducirse su tamao parece que aumenta. Y como sigue siendo enormemente grande la cadena comprimida intentaremos hacerla aun mayor a ver que pasa "; # comprimimos con la funcin gzcompress $c=gzcompress($cadena,9); echo "<br>".$c; # descomprimimos con la funcin gzcompress $dc=gzuncompress($c); echo "<br>".$dc."<br>"; # ahora utilizamos la funcin gzencode $c1=gzencode($cadena,9,FORCE_GZIP); echo "<br>".$c1."<br>"; /* el resultado lo guardamos en un fichero con extensin gz pero abierto en modo "normal", es decir escribiendo dentro del fichero la cadena "tal cual" fue devuelta por gzencode*/ $f=fopen("pepe.gz","w"); fwrite($f,$c1); fclose($f); # abrimos el fichero anterior utilizando las funciones # de lectura de fichero comprimidos $f=gzopen("pepe.gz","r"); readgzfile("pepe.gz"); gzclose($f); # borramos el fichero una vez ledo unlink("pepe.gz"); # otra opcin de compresin de cadenas utilizando la funcin # gzdeflate $c2= gzdeflate($cadena,9); echo "<br><BR>".$c2; # con la funcin gzinflate podemos descomprimir la cadena # comprimida generada por gzdeflate $dc2=gzinflate($c2); echo "<br>".$dc2; ?>
ejemplo175.php

Funciones para buferizacin de salidas


ob_start()

Esta funcin activa la buferizacin de las salidas generadas por el script de PHP a partir de su activacin. Dicho de otra forma, impide que las salidas generadas por el script se enven al cliente impidiendo que sean visualizadas en el navegador. A partir del momento de activar esa buferizacin, todas las salidas generadas se almacenan en una variable especfica llamada: ob_get_contents() ob_end_clean()

Esta funcin desactiva la buferizacin iniciada por ob_start y borra los contenidos de la variable ob_get_contents() ob_clean()

Esta funcin vaca el buffer de salida pero sin desactivar la bufferizacin. Las salidas posteriores a esta funcin seguiran siendo recogidas en el buffer.

Cabeceras para transferir informacin comprimida


Cuando un servidor recibe una peticin de una pgina web el navegador del cliente siempre enva informacin sobre su disposicin a aceptar diferentes tipos de contenidos. Una de las informaciones que suelen recibirse con la peticin del navegador se refiere a su capacidad para aceptar contenidos codificados y esto suelen hacerlo mediante el envio de una cabecera que dira algo similar a esto: Accept-Encoding:gzip,deflate o Accept-Encoding: gzip. Esta posibilidad es una caracterstica comn a todas las versiones modernas de los navegadores (es posible que algunas versiones antiguas no acepten esta codificacin) y bastar con que se incluya en la respuesta (el documento transferido por el servidor al cliente) la cabecera: Header('Content-Encoding: gzip') para que el navegador sepa que la informacin llegar codificada y que debe activar -de forma automtica- sus mecanismos de traduccin de ese tipo de contenidos.

Algunas limitaciones
En todos estos ejemplos hemos dado por supuesto que los navegadores de los clientes aceptan la codificacin gzip, pero es evidente que si eso no ocurriera la pgina se visualizara errneamente.

Economizando espacio en el servidor


Las opciones de compresin pueden permitirnos un cierto ahorro de espacio de servidor. Las pginas HTML podran almacenarse comprimidas y ser llamadas a travs de un script de descompresin que permita visualizarlas. En este ejemplo se efecta la compresin de una pgina web (una de las pginas de estos materiales guardada en formato HTML) cuyo tamao original es de 57.105 bytes. El fichero comprimido resultante ocupa 12.371 bytes. Como vers, el fichero se reduce a poco ms del 20% del original.

<? # Creamos una variable "vacia" $cadena=""; # Abrimos el fichero en modo lectura (r) $f1=fopen("prueba.html","r"); /* hacemos un bucle para leer el fichero hasta encontrar el final (feof) y vamos recogiendo el contenido en la variable */ while (!feof($f1)) { $cadena .= fgets($f1, 1024); } /*comprimimos la cadena con gzencode con lo cual la propia funcin aade los "encabezados" de formato gzip*/ $c1=gzencode($cadena,3,FORCE_GZIP); /* abrimos un nuevo fichero modo escritura (w) con "fopen", es decir como un fichero normal con extensin GZ */ $f=fopen("prueba.html.gz","w"); /* escribimos la cadena "tal cual" en este fichero */ fwrite($f,$c1); # cerramos el fichero comprimido fclose($f); echo "La compresin ha terminado"; ?>
ejemplo176.php

El fichero comprimido mediante el script anterior no puede ser visualizado directamente. Requiere ser descomprimido antes de ser enviado al navegador. Y eso podra hacerse mediante un script como este:

<?php #abrimos el fichero comprimido con "gzopen" $f=gzopen("prueba.html.gz","r"); /* leemos el contenido completo en forma transparente ya que readgzfile descomprime la salida*/ readgzfile("prueba.html.gz"); # cerramos el fichero gzclose($f); ?>
Visualizar fichero comprimido

Economizando tiempo de transferencia


No solo se puede economizar espacio en el servidor. Tambin es posible enviar comprimidas -desde el servidor hasta el cliente- las pginas web. En ese caso, ser el propio navegador el que interprete la informacin comprimida y la presente de una manera transparente. Lo que habremos ahorrado habr sido tiempo de transferencia pero, igual que ocurra en el comentario anterior, esa reduccin del volumen de informacin a transferir afecta nicamente al contenido de la pgina y no a otros elementos que puede incluir, tales como imgenes, etctera. Este es un ejemplo de un script que comprime una pgina web y la enva comprimida al cliente.

<?php /* activamos la bufferizacin de la salida para que no se presenten los resultados del script directamente en la pgina Cuidado con no dejar lneas en blanco delante del script ya que vamos a insertar luego Headers!! */ ob_start(); # abrimos y leemos el fichero html $f1=fopen("prueba.html","r"); fpassthru($f1); # recogemos el contenido del buffer en la variable $cadena $cadena = ob_get_contents(); # comprimimos la cadea con gzencode # para que incluya los encabezados "gzip" $cd=gzencode($cadena,3,FORCE_GZIP); # desactivamos la "buferizacin" # y borramos el contenido del buffer ob_end_clean(); # insertamos la cabeceras # indicando el tipo de contenido y el tamao Header('Content-Encoding: gzip'); Header('Content-Length: ' . strlen($cd));; # presentamos el contenido (cadena comprimida) que ser # "traducido" automticamente por el navegador echo $cd; ?>
Ejecutar script

El ejemplo anterior comprima el contenido del fichero antes de enviarlo. En este que incluimos a continuacin partimos del supuesto de que la pgina ya est comprimida en el servidor. Por tanto, tendremos que leer el fichero comprimido y enviarlo, de igual forma, al cliente.

<?php ob_start(); /* En este caso abrimos el fichero con "gzopen" ya que se trata de un fichero comprimido # todo lo dems es idntico al ejemplo anterior*/ $f1=gzopen("prueba.html.gz","r"); gzpassthru($f1); $cadena = ob_get_contents(); $cd=gzencode($cadena,3,FORCE_GZIP); ob_end_clean(); Header('Content-Encoding: gzip'); Header('Content-Length: ' . strlen($cd)); echo $cd; ?>
Ejecutar script

Funciones FTP Requisitos del sistema


El uso de estas funciones requiere que PHP tenga activada la opcin FTP (enabled), que en nuestro caso est activada en la configuracin por defecto, tal como puedes ver a travs de tu info.php, que tendr un apartado idntico al que observamos en la siguiente imagen.

Esto en cuanto a PHP. Pero adems de esta configuracin ser imprescindible disponer de un servidor FTP accesible y activo. En este tipo de transferencias intervienen dos servidores: el servidor HTTP (nuestro Apache) y el servidor FTP, cuyo procedimiento de instalacin y configuracin hemos descrito en el apartado Servidor de FTP. Antes de poder utilizar las funciones que aqu describimos debers tener instalado y activo el servidor FTP que all se describe. Nos conviene tener muy presente que esta versin de PHP parece no admitir localhost como nombre de servidor (en la versin 4 esto no ocurra) y que por esa razn hemos de referirnos al servidor FTP mediante su direccin IP (127.0.0.1, valor por defecto para nuestro servidor de pruebas en modo local) y que hemos creado diferentes usuarios (con privilegios distintos) entre ellos admin.

Transferencias FTP
En la pgina anterior hemos hablado de la manera de transferir informacin entre el ordenador de un usuario y un servidor web. Aqu trataremos algo similar a primera vista un poco distinto. Es el caso de las transferencias en los dos sentidos entre servidores (un servidor HTTP y un servidor FTP). En la configuracin descrita en la instalacin del servidor FTP hemos establecido que ambos servidores tengan sus root en el mismo equipo, pero esa no es la nica opcin posible. Es totalmente factible que uno de los servidores est alojado en un equipo situado fsicamente en Londres y el otro lo est en Sydney, por poner un ejemplo de lugares distantes. Imaginemos que todo esto es cierto. Los dos primeros pasos para poder utilizar las funciones FTP han de ser: abrir la conexin y pasar el login. El ltimo sera cerrar la conexin.

Abrir la conexin

$identificador=ftp_connect (host,puerto)

Esta funcin en la que host es una cadena con el nombre del servidor FTP (no te olvides de ponerlo entre comillas) y puerto es el nmero del puerto a travs del cual se efecta la conexin FTP abre una conexin con el servidor FTP. Si se omite puerto se asigna por defecto el valor 21 que es el habitual para este tipo de servidores. La variable $identificador recoger un identificador de conexin que ser utilizado por las dems funciones.

Loguearse
Utilizaremos este trmino del argot informtico horrible, verdad? para referirnos al hecho de que el usuario se acredite comoautorizado en el servidor FTP. ftp_login($identificador,usuario,contrasea)

Una vez abierta la conexin es preciso comenzar la sesin utilizando la funcin ftp_login con los siguientes parmetros: $identificador, que es la variable en la que se recoga el resultado de ftp_connect. usuario, que es el nombre de usuario. contrasea, que es la contrasea de acceso del usuario. Esta funcin devuelve un valor booleano que ser 1 en el caso en que se inicie la sesin correctamente o NUL si no lo hace.

Cerrar la conexin
Mediante la funcin: ftp_quit($x)

se cierra la conexin abierta con el identificador indicado en la variable $identificador.

<?php # conexin con el servidor FTP if($x=@ftp_connect ("127.0.0.1",21)){ echo "Conexin FTP activada<br>"; }else{ echo "No se activo lo conexin FTP<br>"; } # registro de usuario if(@ftp_login($x,"super","superi")){ echo "El login y la password han sido aceptados"; }else{ echo "Error en login o password"; } #desconexin ftp_quit($x); ?>
ejemplo180.php

Gestin de directorios en el servidor FTP


Una vez logueados y con la conexin activa, ya podremos utilizar funciones FTP tales como:

ftp_cdup($identificador)

Nos sita en el directorio raz del servidor FTP. ftp_pwd($identificador)

Devuelve una cadena con el nombre del directorio actual. ftp_chdir($identificador, otro_directorio)

Cambia el acceso del directorio actual al especificado por la cadena otro_directorio, en caso de que exista. ftp_pwd($identificador)

Devuelve una cadena que contiene el nombre del directorio actual. ftp_mkdir($identificador, nuevo_directorio)

Crea un subdirectorio en el directorio actual cuyo nombre es el nombre indicado en la cadena nuevo_directorio. ftp_rmdir($identificador, nombre_directorio)

Borra el directorio especificado en la cadena nombre_directorio. Para que un directorio pueda ser borrado se requiere que est vacoy que sea un subdirectorio del directorio actual.

Informacin sobre los contenidos de los directorios del servidor FTP


ftp_nlist($identificador, nombre_directorio)

Devuelve una array escalar con los nombres de los ficheros y subdirectorios contenidos en el directorio que se indica ennombre_directorio. Si se trata del directorio actual, el parmetro nombre_directorio puede especificarse como una cadena vaca (""). Si la informacin se refiere a un subdirectorio del actual bastar con poner su nombre como valor del parmetro nombre_directorio. En cualquier otro caso nombre_directorio contendr la ruta completa. ftp_rawlist($identificador, nombre_directorio)

Igual que la funcin anterior, ftp_rawlist tambin devuelve un array escalar, pero en este caso con informacin ampliada. Este array detalla, adems del nombre del fichero, el tamao, el tipo, la fecha de la ltima modificacin y los permisos de lectura y/o escritura.

<?php if($x=@ftp_connect ("127.0.0.1",21)){ echo "Conexin FTP activada<br>"; }else{ echo "No se activo lo conexin FTP"; } if(@ftp_login($x,"webmaster","webmaster")){ echo "El login y la password han sido aceptados<BR><BR>"; }else{ echo "Error en login o password";

} $lista=ftp_nlist($x,"/php/images"); foreach($lista as $c=>$v){ print "Indice: ".$c." Valor: ".$v."<br>"; } print "<H1>Lista completa</H1>"; $listacompleta=ftp_rawlist($x,"/php/images"); foreach($listacompleta as $c=>$v){ print "Indice: ".$c." Valor:".$v."</br>"; } ftp_quit($x); ?>
ejemplo181.php

El resultado de la ejecucin del script anterior podra producir una salida similar a esta:

Tal como puedes ver en la imagen, la cadena devuelta por la funcin ftp_rawlist tiene dos resultados distintos. La primera de las cadenas comienza por lo cual indica que se trata de un archivo y documento. En el segundo de los casos, se primer carcter es d e indica que se trata de un directorio. Los nueve caracteres siguientes especifican los permisos de acceso a los ficheros y/o directorios. Se subdividen en tres bloques de igual tamao que corresponden a los tres niveles de usuarios habituales en sistemas Unix/Linux (propietario, grupo y resto de usuarios). Para nuestros propsitos bastar con que consideremos los privilegios del primer bloque, es decir los del propietario. El primero carcter de cada bloque slo puede ser r . Si se trata de un fichero y est marcado con r indica que se permite el acceso a l en modo lectura y si se trata de un directorio indica que est permitida la visualizacin de su contenido. El segundo de los caracteres (puede ser w ) indica, si se trata de un fichero, que est permitida la modificacin del fichero. Cuando se trata de un directorio significa que se pueden aadir o suprimir ficheros. El tercero de los caracteres indicara (x ) que el fichero -si se trata de un ejecutable- tiene permisos para ser ejecutado. Cuando se trata de un directorio, indica que pueden conocerse los atributos de los ficheros que contiene y que est permitido el acceso a l y a sus subdirectorios. El signo significa la negacin del atributo en todas las opciones. El siguiente carcter, el nmero 1, est asociado con sistemas Linux/Unix e indicara el nmero de vnculos duros contra el archivo, que es otra cosa que una forma de asignar nombres distintos a un mismo fichero.

Los dos grupos siguientes -parece que no demasiado relevantes para nuestros propsitos- son los nombres del usuario y grupo al que pertenece. A continuacin aparece el tamao del archivo (cero si se trata de un directorio), la fecha y hora de su creacin y el nombre del archivo o directorio.

Transferencia de ficheros
Las transferencias de ficheros pueden realizarse en ambos sentidos.

Desde el servidor FTP hasta el servidor HTTP


Mediante la funcin: ftp_get( $identificador, nombre_en_servidor_web, nombre_en_servidor_ftp, modo)

se transfiere un fichero desde un servidor FTP hasta un directorio del servidor HTTP en el que se est ejecutando PHP. La cadenanombre_en_servidor_web contiene el nombre con el que el fichero ser copiado en el directorio actual del servidor web y la cadenanombre_en_servidor_ftp contiene el nombre (incluyendo el path) que tiene (en el servidor FTP) el fichero que debe ser trasferido. El parmetromodo puede contener uno de estos valores: FTP_ASCII o FTP_BINARY

Desde el servidor HTTP hasta el servidor FTP


Para realizar transferencias en sentido opuesto al anterior se utiliza la siguiente sintaxis: ftp_put($identificador, nombre_en_servidor_ftp, nombre_en_servidor_web, modo)

Se comporta de forma idntica a la funcin anterior. La cadena nombre_en_servidor_ftp sigue siendo el nombre y el path del servidor FTP (donde vamos a copiar el fichero) y nombre_en_servidor_web contiene el nombre del fichero en el servidor web (origen de la transferencia).

Modificacin de ficheros en el servidor FTP


ftp_rename($identificador,nombre_actual,nuevo_nombre)

Cambia el nombre del fichero nombre_actual por el indicado en la cadena nuevo_nombre. ftp_delete($identificador,nombre_fichero)

Elimina -en el servidor FTP- el fichero indicado en la cadena nombre_fichero.

Informacin sobre ficheros del en el servidor FTP


ftp_size($identificador,nombre_fichero)

Devuelve el tamao (en bytes) del fichero que se indica en la cadena nombre_fichero. ftp_mdtm($identificador,nombre_fichero)

Esta funcin devuelve la fecha de la ltima modificacin del fichero indicado en la cadena nombre_fichero. Esta fecha se indica entiempo Unix.

Un ejemplo de uso de las funciones FTP

<?php # Conexin con el el servidor ftp utilizando su direccin IP if(!$x=@ftp_connect ("127.0.0.1",21)){ echo "No se activo lo conexin FTP"; exit(); } # Identificacin de usuario webmaster (manejaremos ficheros en Apache) if(!@ftp_login($x,"webmaster","webmaster")){ echo "Error en login o password"; exit(); } /* comprobamos el nombre del directorio actual del servidor FTP que ser el root correspondiente al usuario registrado (aparecr /) */ echo "El directorio actual es: ",ftp_pwd($x),"<br>"; /* intentamos cambiar a un subdirectorio indicando la ruta absoluta partiendo del directorio root del usuario actual. En caso de error (ruta incorrecta o falta de permisos de accesos nos dara un mensaje de error. Si el cambio tiene xito nos indicara el nombre del nuevo directorio */ if(!@ftp_chdir($x,"/miphp/pdf")){ print "No tienes permisos de acceso a este directorio<br>"; print "o la ruta es incorrecta.Comprueba los datos!<br>"; }else{ echo "Hemos cambiado al directorio: ",ftp_pwd($x),"<br>"; } # comprobamos el nombre del sistema operativo del servidor de FTP echo "El S.O: del servidor FTP es: ",ftp_systype ($x),"<br>"; /* obtenemos una matriz conteniendo la lista de ficheros y directorios del subdirectorio "miphp/fuentes" del del directorio actual*/ $lista=ftp_nlist($x,"/miphp/fuentes"); # escribimos la lista de ficheros contenidos en ese directorio echo "Lista de ficheros del subdirectorio miphp/fuentes<br>"; foreach ($lista as $valor){ echo $valor,"<br>"; } # obtenemos una lista completa de los contenidos de ese subdirectorio $lista=ftp_rawlist($x,"/miphp/fuentes"); # ordenamos el array que contiene la lista anterior sort($lista); echo "Contenidos del subdirectorio miphp/fuentes<br>"; /* extrae los elementos del array eliminando los espacios repetidos mediante la funcion preg_replace en la que \s+ indica uno o ms espacios que sern sustituidos por uno solo (' ') */ foreach($lista as $v){ $v=preg_replace('/\s+/', ' ', $v); # imprimimos la cadena completa print "<br><br><br>".$v."<br>"; # convertimos la cadena en un array # utilizando los espacios como separadores $extrae=explode(" ",$v); # leemos los elementos del array y comentamos sus valores foreach($extrae as $indice=>$cont){ switch($indice){ case 0: print "El elemento de indice".$indice." es: ".$cont."<br>"; if (substr($cont,0,1)=="d"){ print "Es un directorio<br>"; }elseif(substr($cont,0,1)=="-"){ print "Es un fichero<br>"; } if (substr($cont,1,1)=="r"){ print "Tiene permisos de LECTURA<br>";

}elseif(substr($cont,1,1)=="-"){ print "No tiene permisos de LECTURA<br>"; } if (substr($cont,2,1)=="w"){ print "Tiene permisos de ESCRITURA<br>"; }elseif(substr($cont,2,1)=="-"){ print "No tiene permisos de ESCRITURA<br>"; } break; case 4: print "El tamao de este fichero es: ".$cont." bytes<br>"; break; case 8: print "El nombre del fichero o directorio es: ".$cont."<br>"; break; } } } # regresamos al directorio miphp ftp_chdir($x,"/miphp/"); /* creamos un subdirectorio (del directorio actual que es miphp) con nombre experimento anteponiendo @# para evitar mensajes de error en caso de que ya existiera */ @ftp_mkdir($x,"experimento"); /* copiamos el fichero enol.jpg desde el directorio que se indica en el tercer parmetro (miphp) al directorio del servidor FTP que se indica en el segundo parmetro. Le ponemos por nombre lago_enol.jpg */ ftp_put($x, "../miphp/experimento/lago_enol.jpg", "../miphp/enol.jpg",FTP_BINARY); # obtenemos el tamao del fichero transferido echo "El tamao de fichero tranferidos es: ", ftp_size($x,"../miphp/experimento/lago_enol.jpg")," bytes<br>"; /* escribimos la fecha de la ltima modificacin del fichero transferido que coincidir con la fecha y hora en la que se realiz la transferencia. Convertimos a formato de fecha convencional el tiempo UNIX que devuelve la funcin ftp_mdtm */ print "La fecha de modificacion del fichero es:"; print date("d-m-Y H:i:s",ftp_mdtm($x,"./experimento/lago_enol.jpg")); # cambiamos el nombre del fichero lago_enol.jpg por lago_covadonga.jpg # en el servidor FTP @ftp_rename($x,"./experimento/lago_enol.jpg", "./experimento/lago_covadonga.jpg"); /* creamos un enlace de descarga directa del fichero haciendo una llamada mediante el protocolo ftp:// utilizando la sintaxis: ftp://usuario:contrasea@nombre del servidor seguidos de la ruta (en el servidor FTP) y el nombre del fichero */ print "<BR><a href='ftp://webmaster:webmaster@localhost"; print "/miphp/experimento/lago_covadonga.jpg'> Descargar</a>"; /* transferimos al directorio miphp con nombre liborio.jpg un fichero procedente del directorio experimento cuyo nombre es lago_covadonga.jpg*/ ftp_get($x,"../miphp/liborio.jpg", "./experimento/lago_covadonga.jpg",FTP_ASCII); /* comprimimos un fichero alojado en miphp para transferirlo comprimido al servidor FTP */ #empezamos leyendo el fichero y guardndolo en una cadena $cadena=""; // inicializamos la variable con una cadena vaca $f1=fopen("cabina.jpg","r"); while (!feof($f1)) { $cadena .= fgets($f1,1024); }

fclose($f1); # comprimimos la cadena obtenida del fichero anterior $c1=gzencode($cadena,3,FORCE_GZIP); # guardamos la cadena comprimida en un fichero $f=fopen("cabina.jpg.gz","w"); fwrite($f,$c1); fclose($f); /* al servidor el fichero comprimido. No es necesario indicar la ruta actual ya que ha sido creado en el mismo directorio en el que se est ejecutando el script */ ftp_put($x, "./experimento/cabina.jpg.gz", "cabina.jpg.gz",FTP_BINARY); #eliminamos el fichero comprimido del directorio miphp unlink("cabina.jpg.gz"); # cerramos la conexin con el servidor ftp ftp_quit($x); # establecemos un enlace de descarga para el fichero comprimido print "<BR><a href='ftp://webmaster:webmaster@localhost"; print "/miphp/experimento/cabina.jpg.gz'>Descarga comprimido</a>"; ?> Cuidado! Observa los path de los ejemplos. Al anteponer ../ estaremos indicando una ruta absoluta desde al root de servidor FTP y con ./ aludimos a un subdirectorio del actual. Si vas a utilizar el ejemplo anterior presta mucha atencin a los nombres de los directorios y adecalos a la configuracin de tu servidor. Al ejecutar el script del ejemplo anterior por segunda vez (sobre Linux Ubuntu) puede aparecerte un mensaje de error del tipo overwrite permission denied. Este problema puede ser causado por un defecto de configuracin del sevidor FTP. Hemos podido comprobar que, algunas veces, por una extraa razn, aparecen en el fichero de configuracin dos lneas segudas dicendoAllowOverwrite Off y AllowOverwrite On. La configuracin correcta es AllowOverwrite On (para permitir sobreescribir). Bastara con eliminar la lnea marcada con Off (o reemplazar el Off por On) para solventar el problema.

Mensajes de correo Correo electrnico


PHP dispone de una funcin que permite el envo de todo tipo de mensajes de correo electrnico desde una pgina web. Son escasos los hosting que tienen activada esta funcin. El motivo aducido por muchos de ellos para establecer esta restriccin es el riesgo de abusosmediante los mensajes conocidos como spam. Como siempre, si tu inters es publicar y tienes necesidad de este servicio, procura consultar sobre la disponibilidad de este servicio.

Requisitos del sistema


La utilizacin de las funciones de correo electrnico requiere disponer de un servidor de correo electrnico instalado y activo y la modificacin de la configuracin inicial del fichero php.ini. Si no tienes instalado este servidor puedes hacerlo ahora. En la pgina Servidor de correo tienes detallados ambos procesos (instalacin y modificacin de php.ini).

Sintaxis
La forma ms simple de la funcin de correo es esta:

mail(destinatario,asunto,mensaje)

Dnde destinatario es la direccin del destinatario, asunto es el texto que aparecer como Asunto en el encabezado que recibir el destinatario y mensaje el texto que aparecer en el cuerpo del mensaje. No te olvides de escribir entre comillas esos tres parmetros de la funcin.

<? # insertamos la funcin mail (rojo) dentro de un condicional # para tener una confirmacin de envio y/o aviso de error # es algo muy habitual para conocer el exito de la ejecucin # de funciones if(mail("juan@mispruebas.as", "Mi primer mensaje","Este es el texto")){ print "mensaje enviado"; }else{ print "el mensaje no ha podido enviarse"; } ?>

Mensaje con cabeceras MIME


Una forma ms completa es la siguiente: mail(destario,asunto,mensaje,cabecera)

Como puedes ver, en este caso aadimos un nuevo parmetro a la funcin (cabez) que debe estar entre comillas y que puede contener, separando con comas, lo siguiente: From: Nombre <e-mail> El texto que escribas en el parmetro Nombre (cuidado, no lleva comillas!) ser el nombre del remitente, que aparecer en el campo De: cuando el destinatario reciba el mensaje. Donde dice e-mail es obligado escribir una direccin de correo que debe ir contenida entre < y >, tal como puedes ver en el ejemplo. Reply-To: correo En una nueva lnea, y sin cerrar las comillas de la cadena iniciada en el encabezado anterior, podemos indicar la direccin de respuesta del mensaje. La direccin que escribamos donde dice correo (fjate que no va entre comillas) ser la direccin a la que se enviar la respuesta si el destinatario una vez recibido tu correo desea responder mediante la opcin Responder de su programa de correo electrnico. Cc: correo1,correo2,... De igual forma que en el caso anterior en una nueva lnea y sin cerrar comillas podemos incluir en correo1, correo2, etctera, las direcciones de correo de las personas a las que deseamos enviar copia del mensaje. No te olvides de separar con comas cada una de las direcciones que, como puedes ver en los ejemplos, no van entre comillas. Bcc: correo1,correo2,... Esta opcin es idntica a la anterior en cuanto a su funcionamiento, con la nica diferencia de que esas direcciones no sern visibles por los destinatarios de los mensajes. X-Mailer:PHP/".phpversion() Es una frivolidad que se puede incluir en el encabezado del mensaje y que indica que versin de PHP con que ha sido creado.

Cuidado! Debemos insistir en sugerirte una especial atencin a la sintaxis de este tipo de scripts. Los contenidos generados por la funcin mail deben ser interpretados por el servidor de correo y tanto en este caso como en los que veremos a continuacin los requisitos de formato de estos servidores son muy estrictos. De no adaptarse exactamente a sus especificaciones pueden producirse efectos extraos tales como: envos incorrectos y/o apariencias indeseadas en los mensajes. <?

mail("juan@mispruebas.as","Varios destinatarios","Cuerpo del mensaje", "From: php <juan@mispruebas.as> Reply-To: andres@mispruebas.as Cc: perico@mispruebas.as,andres@mispruebas.as Bcc:andres@mispruebas.as,perico@mispruebas.as X-Mailer: PHP/" . phpversion()); ?>

En el ejemplo anterior insertaremos los nuevos elementos. Observa con mucha atencin la estructura del cdigo. Fjate que hemos insertado en lneas diferentes cada uno de los conceptos: From, Reply-To, etctera y que no hemos dejado ningn espacio al comienzo de esas lneas. No es por capricho ni por afn esttico. Si insertramos algn carcter delante de esas lneas se plantearan problemas en la estructura del mensaje y si no incluyramos un salto de lnea para cada uno de los conceptos tambin tendramos ese mismo problema. La sintaxis MIME es muy estricta en este sentido. Tengamos mucho cuidado en esto! Hay otra posibilidad sintctica como alternativa a los saltos de lnea ya conocida. Podramos escribir todo en una sola lnea sustituyendo los saltos de lnea que ves aqu por \n, de forma que el script tuviera un aspecto similar al siguiente: mail("juan@localhost","Asunto","Contenido","\nReply-To: ...\nCc:.....\nBcc: ...") donde, como ves, los \n sustituyen a los saltos de lnea.

El mismo ejemplo, utilizando variables


Aqu tenemos un ejemplo donde los parmetros de envo proceden de variables PHP. Recordemos que esas variables pueden transferirse mediante un formulario a un script que se encargue de su envo. Como puedes observar, hemos puesto las direcciones de los destinatarios de las copias visibles y ocultas en sendos arrays y hemos aadido una funcin que: lee los array, los une en una cadena separndolos con comas y, por ltimo, quita la ltima coma aadidautilizando la funcin substr.

<? #variables destinatario, asunto, texto, etc. $destino="andres@mispruebas.as"; $envia="Andrs PHP"; $remite="andres@mispruebas.as"; $asunto="Mensaje experimental"; $texto="Esto es una prueba. No es spam"; #array de destinatarios de copias visibles $c[0]="perico@mispruebas.as"; $c[1]="juan@mispruebas.as"; #crear la cadena con las direcciones # y aadir las comas de separacin $cco=""; //creamos la variable (vacia) foreach($c as $pegar) { $cco .=$pegar; $cco.=","; }; #quitamos la coma del final de la cadena $l=strlen($cco);

$cco=substr($cco,0,$l-1); #array de destinatarios de copias OCULTAS $b[0]="perico@mispruebas.as"; $b[1]="andres@mispruebas.as"; #crear la cadena con las direcciones # y aadir las comas de separacin $bco=""; //creamos la variable (vacia) foreach($b as $pegar) { $bco .=$pegar; $bco.=","; }; #quitamos la coma del final de la cadena $l=strlen($bco); $cco=substr($bco,0,$l-1); mail($destino, $asunto, $texto, "From: $envia <$remite> Reply-To: $remite Cc: $cco Bcc:$bco X-Mailer: PHP/" . phpversion()); ?>

Formatos MIME Funciones PHP requeridas para el envo de mensajes


Podrs ver a lo largo de los ejemplos de envo de mensajes de correo electrnico algunas funciones raras que vamos a comentar seguidamente: uniqid(prefijo,booleano)

Genera un identificador nico basado en la hora actual del sistema, expresada en microsegundos y con una longitud de 13 caracteres. El parmetro prefijo permite establecer una cadena o nmero (puede ser una cadena vaca) que se antepone al identificador generado por la funcin. Opcionalmente permite el segundo parmetro booleano que debe ser un valor booleano (TRUE FALSE) o tambin 0 1. Cuando este parmetro es TRUE aade al final de la cadena generada anteriormente otra subcadena numrica -generada aleatoriamente- de nueve dgitos, que refuerza la unicidad del identificador. preg_replace(busca, reemplaza, cadena)

Busca en la cadena especificada en el parmetro cadena (que puede ser una cadena o una variable que contenga una cadena) las subcadenas especificadas en busca (recuerda que debe llevar delante y detrs un carcter delimitador tal como puedes ver en lasexpresiones regulares) y sustituye esas subcadenas por el contenido del parmetro reemplaza. Devuelve la cadena modificada. strip_tags(cadena, excepciones)

Suprime todas las etiquetas HTML contenidas en cadena salvo las que se indiquen en excepciones. Por ejemplo: strip_tags($cadena, '<i><u><b>') eliminara todas las etiquetas HTML, salvo las indicadas aqu y sus correspondientes cierres. Si no se especifican excepcioneselimina todas las etiquetas.

base64_encode(cadena)

Devuelve una cadena codificada en base64. Esta codificacin se hace para permitir que las informaciones binarias puedan ser correctamente manipuladas por sistemas que no generan correctamente los 8 bits, tal como ocurre frecuentemente en los cuerpos de los mensajes de correo electrnico. base64_decode(cadena)

Realiza el proceso inverso a la anterior. Decodifica una cadena previamente codificada en base64. chunk_split(cadena, longitud, separador)

Devuelve una cadena obtenida al insertar en la cadena especificada -a intervalos del nmero de caracteres especificados en el parmetro numrico longitud- el contenido de una subcadena indicada en el parmetro separador. Por defecto -cuando no se especifican los parmetros- longitud es igual a 76 caracteres y el separador es la cadena \r\n (retorno y salto de lnea). Esta funcin se utiliza para convertir al formato especificado en la RFC 2045 (especificacin para MIME) las cadenas obtenidas porbase64_encode. Es el formato habitual de los ficheros adjuntos de los e-mail.

Formato de los mensajes de correo electrnico


En la pgina anterior hemos hablado acerca de la manera de enviar un e-mail y veamos la forma de insertar el cuarto parmetro de la funcin mail para incluir algunos elementos de los encabezados MIME. El formato de los mensajes est especificado en una serie de normas conocidas como el MIME (Multipurpose Internet Mail Extensions) en las que se establecen los contenidos y la sintaxis de las diferentes partes de un mensaje. Recordemos que la funcin mail(destinatario, asunto, mensaje, cabecera)

tiene cuatro parmetros y que las especificaciones del MIME aluden a los dos ltimos, es decir a mensaje (el cuerpo del mensaje) ycabecera que es el encabezado del mismo. Respecto a destinatario y asunto no se requieren ms comentarios que reiterar la necesidad de incluir esos valores (e-mail del destinatario y asunto) bien directamente, como parmetro en la funcin, o a travs de una variable tal como hemos comentado en la pgina anterior.

Cabeceras de los mensajes


Los diferentes elementos de la cabecera de un mensaje deben insertarse siempre separados por saltos de lnea bien pulsandoEnter o incluyendo la secuencia \n dentro de la misma de lnea. No pueden incluirse espacios, ni al comiezo de las nuevas lneas ni despus de \n, y las comillas que han de contener todo el encabezado se abren delante del primero de ellos y no se cierran hasta despus de haber escrito el ltimo. Pueden contener lo siguiente: Date: xxxxx

Date: debe escribirse con esta sintaxis exactamente. El parmetro xxxxx es una cadena que contendr la fecha de envo del mensaje y que puede obtenerse a travs de una de las funciones de fecha de PHP tal como puedes ver en el ejemplo. MIME-Version: 1.0

Este elemento de la cabecera especificar la versin MIME que ha de utilizar el cliente de correo para poder interpretar adecuadamente el contenido de los mensajes. From: remitente<e-mail>

Este elemento de la cabecera permite indicar el nombre del remitente (remitente) y su direccin e-mail siguiendo la sintaxis que se especifica. El nombre, como un elemento independiente y la direccin e-mail dentro de < >. Cuidado!

No debemos poner comillas ni en el nombre del remitente, ni en la direccin e-mail, ni en la fecha, etctera. Respecto a Cc: y Bcc: ; Reply-To: y X-Mailer: son vlidos los comentarios que hemos hecho en la pgina anterior. Si no se especifica lo contrario, los mensajes se envan como texto sin formato, pero existen opciones que permiten especificar el formato que ha de tener un mensaje. La especificacin de un formato obliga a incluir otro elemento en cabecera del mensaje: Content-Type:

Este elemento debe ir seguido de la especificacin en la que se indique el tipo de contenido. Tiene la sintaxis: tipo/subtipo. El MIME establece un gran variedad de opciones para este propsito. Hablaremos de dos de ellas: text/plain El text/plain es la opcin por defecto y seala que el contenido del mensaje es de tipo texto (text) y del subtipo sin formato (plain) text/html Como la opcin anterior, es tipo texto, pero en este caso, el subtipo es html con lo cual el mensaje se visualizar en formato htmlsiempre que el cliente de correo permita esa posibilidad. Los tipos anteriores permiten enviar mensajes simples (sin ficheros adjuntos) en uno u otro formato, pero el MIME nos da opciones para insertar dentro de un mismo mensaje elementos de diferentes tipos y subtipos. Las opciones de mayor inters son las siguientes: multipart/alternative Es la forma de especificar que el mensaje tiene varias partes (multipart) de las que el destinatario ha de ver una sola (alternative). Se podra utilizar en casos en los que sea necesario prever la posibilidad de que un mensaje con formato HTML pueda ser visualizado como texto plano cuando el cliente de correo no soporte HTML. Podemos hacer un mensaje a medida que se presentar de una forma u otra segn el cliente utilizado para leerlo. multipart/mixed Cuando en el Content-Type se establece el tipo multiparte y el subtipo mezclado (mixed) ser cuando tengamos la posibilidad deadjuntar ficheros al mensaje. Las diferentes partes de un mensaje deben ir separadas tanto en modo alternativo como mezclado y para ello hay que incluir un nuevo elemento en el encabezado. Se trata de un separador al que se llama boundary. boundary=cadena

Dentro del encabezado y siempre en lnea aparte (fjate que en los ejemplos o est en lnea aparte o aparece el \n) debemos incluir el elemento boundary= (sin smbolo de $ delante) y detrs del signo igual una cadena (en este caso entre comillas) que en principio puede ser una cadena cualquiera que no contenga espacios, aunque lo habitual es incluirla con el formato que podemos ver en los ejemplos.

El cuerpo del mensaje


En su formato ms simple el cuerpo del mensaje contiene nicamente texto, pero cuando se trata de multipartes deber contener necesariamente: los separadores de las diferentes partes, los encabezados de cada una de las partes y sus respectivos contenidos. La secuencia habra de ser de este tipo: Separador Content-type Los tipos y subtipos ms habituales son los siguientes. Para incluir textos: los ya mencionados text/plain y text/html. Para imgenes y segn el tipo de imagen: image/jpeg, image/gif. Para sonidos: audio/basic. Para vdeo: video/mpeg. Para ejecutables,

comprimidos y otros ficheros adjuntos: application/octet-stream. En cualquier caso, si quieres utilizar algn otro tipo de archivo puedes consultar en la web las especificaciones del MIME. Aparte de tipo/subtipo puede aadirse a Content-type -en el caso de texto- separado por punto y coma, la especificacin del tipo de alfabeto (charset=) seguida del tipo de codificacin (te sugerimos el "ISO-8859-1" que hace alusin al alfabeto latino). Cuando se trata de ficheros adjuntos deberemos poner, despus del punto y coma, name= seguido del nombre y extensin del fichero que se adjunta. Content-Transfer-Encoding Este apartado del encabezado puede especificar una de los siguientes codificaciones: 7BIT, 8BIT, BASE64, BINARY,QUOTEDPRINTABLE La transferencia codificada en 7bit representa la codificacin habitual en el formato ASCII de 7 bits. No permite caracteres ASCII con un cdigo mayor que 127. Quoted-printable constituye una de las alternativas al formato ASCII de 7 bits. Esta codificacin suele usarse cuando la mayora de los caracteres del mensaje puede escribirse con formato US ASCII de 7 bits. Prev que los caracteres con cdigos ASCII superiores a 127 se expresen mediante un mecanismo especial evitando, entre otras cosas, que las letras con tilde y algunos otros caracteres especiales se visualicen incorrectamente. Es la forma de codificacin ms recomendable para textos. La codificacin en base64 convierte cadenas binarias en cadenas de texto, con lo cual pueden ser enviadas de forma ms segura. Es la forma de codificacin habitual de las imgenes y los ficheros exe, zip, etctera. Content-Disposition Se utiliza nicamente cuando se insertan ficheros adjuntos. Permite dos opciones: inline o attachment. La primera permite que los contenidos se visualicen junto con el cuerpo del mensaje mientras que bajo la segunda apareceran como ficheros adjuntos. Este elemento del encabezado lleva separada por punto y coma una segunda parte. El filename=, donde se puede especificar entre comillas un nombre y una extensin (igual o distinta de la original) con la que se denominar al fichero en el mensaje recibido. Lectura del fichero Cuando se trata de insertar un fichero el proceso es el tpico de lectura de ficheros, es decir: Hay que crear el identificador de recurso del fichero en modo lectura. Recoger en una variable el buffer de lectura. Cerrar el fichero. Codificacin Una vez recogido en el fichero a transmitir en una variable, el paso siguiente es codificar esa variable.Utilizaremos la codificacin ms habitual y flexible base64 que requerir el uso de las funciones base64_encode y chunk_split. Cuerpo del mensaje La fase final del proceso es la de agrupar los diferentes trozos en una sola variable, que ser la que se insertar como parmetro texto en la funcin e-mail. Separador ..... otra parte ... Separador final

Cuidado! La insercin de ficheros adjuntos requiere que stos estn disponibles en el servidor por lo que, antes de enviarlos, habr que subirlos al servidor utilizando un proceso como el que hemos analizado cuando hablbamos deTransferencia de ficheros.

Las cabeceras MIME de un mensaje

Aqu tienes un ejemplo con los diferentes elementos del encabezado de un mensaje. Como ves, hemos incluido todos los elementos dentro de la funcin mail.

<? mail("juan@mispruebas.as", "Cabeceras", "Prueba de cabeceras", "Date: 24 de Junio de 2001 MIME-Version: 1.0 From: Estudiante Perico<perico@mispruebas.as> Cc:perico@mispruebas.as Bcc:andres@mispruebas.as Reply-To: perico@mispruebas.as X-Mailer: PHP/".phpversion()); ?>

Una forma un poco ms depurada del script anterior podra ser esta que incluimos aqu debajo. Sus particularidades son las siguientes: Recogemos los datos en variables e insertamos en la funcin mail esas variables La variable $cabecera tiene algunas singularidades: La vamos construyendo aadiendo subcadenas: date, from, etc. etc. En cada subcadena dejamos pegado el contenido a las comillas iniciales Al final de cada subcadena (cada una contiene un elemento del encabezado) insertamos \n para el carcter especial que indica a PHP un salto de lnea imprescindible

<? # datos del mensaje $destinatario="juan@mispruebas.as"; $titulo="Cabeceras en variables"; $mensaje="Nueva prueba de cabeceras"; $responder="andres@mispruebas.as"; $remite="andres@mispruebas.as"; $remitente="Otra vez Andres"; //sin tilde para evitar errores de servidor # cabeceras $cabecera ="Date: ".date("l j F Y, G:i")."\n"; $cabecera .="MIME-Version: 1.0\n"; $cabecera .="From: ".$remitente."<".$remite.">\n"; $cabecera .="Return-path: ". $remite."\n"; $cabecera .="X-Mailer: PHP/". phpversion()."\n"; if( mail($destinatario, $titulo, $mensaje,$cabecera)){ echo "mensaje enviado";}else{print "el mensaje no ha podido enviarse"; } ?>

Mensaje con contenido alternativo


<? # creamos la variables "salto" para "mayor comodidad # un salto es la secuencia retorno de carro-nueva lnea # dos saltos es algo similar pero duplicado $UN_SALTO="\r\n"; $DOS_SALTOS="\r\n\r\n"; # creamos el remitente, etc. y tambin la que parte que

# contiene el cdigo HTML del mensaje $destinatario="juan@mispruebas.as"; $titulo="Mensaje alternativo Texto Plano - HTML "; $mensaje="<html><head></head><body bgcolor='#ff0000'>"; $mensaje .="<font face='Arial' size=6>Prueba HTML. </font>"; $mensaje .="aqu pueden ir tildes: , , , , , </body></html>"; $responder="andres@mispruebas.as"; $remite="andres@mispruebas.as"; $remitente="Andres Perez y Perez"; // omitimos las tildes en encabezados para evitar errores de servidor # # # # creamos el separador de bloques del mensaje anteponiento "_separador" aunque podramos haber puesto "tiburcio" generamos un identificador unico utilizando un numero aleatorio como "semilla" y luego lo codificamos con la funcin md5

$separador ="_separador".md5 (uniqid (rand())); # creamos la variable cabecera con los elementos # ya utilizados en los ejemplos anteriores y ponemos al final # de cada elemento UN SALTO DE LINEA $cabecera $cabecera $cabecera $cabecera $cabecera $cabecera $cabecera = "Date: ".date("l j F Y, G:i").$UN_SALTO; .="MIME-Version: 1.0\n"; .="From: ".$remitente."<".$remite.">".$UN_SALTO; .= "Return-path: ". $remite.$UN_SALTO; .="Cc:perico@mispruebas.as".$UN_SALTO; .="Reply-To: ".$remite.$UN_SALTO; .="X-Mailer: PHP/". phpversion().$UN_SALTO;

# AQU DEFINIMOS EL CONTENIDO MULTIPART, fjate que lo acabamos con ";" $cabecera .="Content-Type: multipart/alternative;".$UN_SALTO; # insertamos BOUNDARY (fjate que dejo un espacio # en BLANCO DELANTE y ponemos al FINAL los DOS SALTOS DE LINEA $cabecera .=" boundary=$separador".$DOS_SALTOS; # # # # colocamos el primer separador(con los dos guiones delante) antes de insertar la primera parte del mensaje que es el texto plano para el caso de que el cliente de correo no soporte HTML

$texto_plano ="--$separador".$UN_SALTO; # especificamos el tipo de contenido y la codificacin # e inserto DOS SALTOS AL FINAL ya que ahi acaba la cabecera de esta parte $texto_plano .="Content-Type:text/plain; charset=\"ISO-8859-1\"".$UN_SALTO; $texto_plano .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; # cambiamos las etiquetas "<br>" por saltos de lnea # y luego quitamos todas las etiquetas HTML del cuerpo del mensaje # ya que el texto plano no debe llevar ese tipo de etiquetas $extractor= strip_tags(preg_replace("/<br>/", $UN_SALTO, $mensaje)); $texto_plano .=$extractor; # insertamos un nuevo separador para sealar el final # de la primera parte del mensaje y el comienzo de la segunda

# en este caso ponemos UN SALTO delante del separador ya que de lo contrario # al componer el mensaje se unira con la cadena texto_plano anterior # que no tiene SALTO DE LINEA AL FINAL $texto_html =$UN_SALTO."--$separador".$UN_SALTO; # especificamos el encabezado HTML para el siguiente bloque # y ponemos en la ultima lnea los DOS SALTOS DE LINEA $texto_html .="Content-Type:text/html; charset=\"ISO-8859-1\"".$UN_SALTO; $texto_html .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; #aado la cadena que contiene el mensaje $texto_html .= $mensaje; # insertamos SOLAMENTE un SALTO DE LINEA # estamos al funal del mensaje $texto_html .=$UN_SALTO; # unimos ambas cadenas para crear el cuerpo del mensaje $mensaje=$texto_plano.$texto_html; # enviamos el mensaje utilizando if( mail($destinatario, $titulo, $mensaje,$cabecera)){ echo "mensaje enviado ";}else{print "ha habido errores en el envio"; } ?>

Mensaje con ficheros adjuntos


<? # definimos estas variables igual que en el ejemplo anterior $UN_SALTO="\r\n"; $DOS_SALTOS="\r\n\r\n"; #incluimos en varias, asunto, un texto en HTML # remitente, etc. etc. $destinatario="perico@mispruebas.as"; $titulo="Mensaje con dos fichero adjuntos"; $mensaje="<html><head></head><body bgcolor=\"#ff0000\">"; $mensaje .="<font face=\"Arial\" size=6>Prueba HTML </font>"; $mensaje .="</body></html>"; $responder="andres@mispruebas.as"; $remite="andres@mispruebas.as"; $remitente="Andres otra vez"; # definimos el separador de parte # con el mismo procedimiento del ejemplo anterior $separador = "_separador_de_trozos_".md5 (uniqid (rand())); # insertamos los datos de la cabecera del mensaje $cabecera = "Date: ".date("l j F Y, G:i").$UN_SALTO;

$cabecera $cabecera $cabecera $cabecera $cabecera

.= "MIME-Version: 1.0".$UN_SALTO; .= "From: ".$remitente."<".$remite.">".$UN_SALTO; .= "Return-path: ". $remite.$UN_SALTO; .= "Reply-To: ".$remite.$UN_SALTO; .="X-Mailer: PHP/". phpversion().$UN_SALTO;

# especificamos el tipo de contenido mutipart/mixed # ya que ahora insertaremos ficheros de distinto tipo $cabecera .= "Content-Type: multipart/mixed;".$UN_SALTO; # insertamos el valor de boundary hacindola igual a $separador # y acabamos con DOS SALTOS porque es el FINAL DE LA CABECERA $cabecera .= " boundary=$separador".$DOS_SALTOS; /* Parte primera del envio -Mensaje en formato HTML ================================================ Separador inicial ------------------------------- */ $texto ="--$separador".$UN_SALTO; /* Encabezado parcial ------------------ */ /* especificamos que este primer elemento ser texto y que ir codificado en formato 7 bits */ $texto .="Content-Type: text/html; charset=\"ISO-8859-1\"".$UN_SALTO; $texto .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; /* Contenido de esta parte del mensaje -----------------------------------*/ # ya teniamos escrito el texto del mensaje ms arriba # simplemente lo aadimos a la cadena de texto $texto .= $mensaje; #la variable $texto recoge esta parte del documento # la uniremos al final con las siguientes /* Separador de partes -------------------- */

$adj1 = $UN_SALTO."--$separador".$UN_SALTO; /* Parte segunda de mensaje -Fichero adjunto n 1 ==================================================== */ /* Encabezado parcial ------------------ */ # especificamos el tipo de contenido image/jpeg # ya que ese ser el documento que vamos a enviar # ponemos el nombre del fichero (debemos tenerlo en el servidor # con ese mismo nombre) # establecemos in line como disposicin para que pueda ser visualizado # directamente en el cuerpo del mensajes # en filename le asignamos el nombre con el que queremos que sea # recibido por el destinatario # por ultimo especificamos la codificacion como base64 $adj1 .="Content-Type: image/jpeg;";

$adj1 $adj1 $adj1 $adj1

.=" name=\"casa08.jpg\"".$UN_SALTO; .="Content-Disposition: inline; "; .="filename=\"leoncio.jpg\"".$UN_SALTO; .="Content-Transfer-Encoding: base64".$DOS_SALTOS;

/* Lectura previa del fichero a adjuntar ------------------------------------------ */ # abrimos el fichero en modo lectura (r) # y leemos todo su contenido midiendo previamente # su longitud con filesize # recogemos en $buff el contenido del fichero # y cerramos despus $fp = fopen("casa08.jpg", "r"); $buff = fread($fp, filesize("casa08.jpg")); fclose($fp); /* Codificacin del fichero a adjuntar ------------------------------------------ */ # codificamos en base 64 y troceamos en lineas de 76 caracteres # y aadimos el resultado a la variable adj1 $adj1 .=chunk_split(base64_encode($buff)); /* Separador de partes -------------------- */

$adj2 = $UN_SALTO."--$separador".$UN_SALTO; /* Tercera parte de mensaje -Fichero adjunto n 2 ==================================================== */ /* Encabezado parcial ------------------ */ # los contenidos del encabezado son similares al caso anterior # con la salvedad de que el contenido es ahora # application/octet-stream ya que contiene un fichero ejecutable # y la disposicion es attachment, no tiene sentido tratar # de visualizar un fichero zip $adj2 .="Content-Type: application/octet-stream;"; $adj2 .=" name=\"apachito.zip\"".$UN_SALTO; $adj2 .="Content-Disposition: attachment; filename=\"apachito.zip\"".$UN_SALTO; $adj2 .="Content-Transfer-Encoding: base64".$DOS_SALTOS; /* Lectura previa del fichero a adjuntar ------------------------------------------ */ # abrimos el fichero en modo lectura (r) # y leemos todo su contenido midiendo previamente # su longitud con filesize # recogemos en $buff el contenido del fichero # y cerramos despus $fp = fopen("apachito.zip", "r"); $buff = fread($fp, filesize("apachito.zip")); fclose($fp); /* Codificacin del fichero a adjuntar -----------------------------------------$adj2 .=chunk_split(base64_encode($buff)); */

/*

Separador final YA NO HAY MAS PARTES ---------------------------------------- */

$adj2 .=$UN_SALTO."--$separador".$UN_SALTO; Unin de todas las PARTES ---------------------------------------- */ # unimos en la variable mensaje todos los elementos # y lo hacemos por el orden en el que fueron creados /* $mensaje=$texto.$adj1.$adj2; /* Envio del mensaje ---------------------------------------- */

if(mail($destinatario, $titulo, $mensaje,$cabecera)){ echo "mensaje enviado";}else{print "ha habido problemas"; } ?>

Imgenes dinmicas
Imgenes dinmicas
PHP permite la creacin dinmica de imgenes. Quiere esto decir que una imagen puede ser presentada en la pgina web sin necesidad de ser almacenada previamente en el servidor y, adems, con un contenido que puede ser modificado en cada instante. Esta posibilidad que ofrece PHP puede resultar muy til a la hora de presentar grficos estadsticos ya que permitira utilizar valores actualesobtenidos, por ejemplo, de una base de datos.

Requisitos del sistema


El manejo de imgenes dinmicas requiere que est instalada la librera de PHP llamada php_gd2.dll. En la versin de PHP que estamos manejando se instala por defecto, pero requiere que la configuracin de fichero php.ini tenga activada esta extensin. La hemos activado durante el proceso de configuracin de PHP (para usuarios de Windows) y en instalacin de Apache + PHP (para usuarios de Ubuntu). Podemos probar a abrir este enlace, info.php en el que habremos de encontrar algo similar a lo que ves en esta imagen:

Si eso ocurre habremos comprobado nuestra configuracin es la adecuada para utilizar las funciones PHP de este mbito y estaremos en disposicin de poder generar imgenes dinmicas.

Formatos GIF Aunque son abundantes los materiales que aluden a este formato grfico -incluso en las pginas oficiales PHP- los formatos GIF slo funcionan en modo lectura. Parece ser que existe un conflicto sobre los derechos de propiedad del algoritmo de compresin que se utiliza en los ficheros .gif y eso est obligando a los desarrolladores de PHP a abandonar este tipo de formato. Formatos PNG El formato de imgenes PNG (Portable Network Graphic) nos permite seguir disponiendo de un formato grfico de difusin gratuitacon una funcionalidad similar al GIF en lo que se refiere a transparencias y que junto con la posibilidad de usar tambin el formato JPG va a cubrir las necesidades grficas de esta utilidad de PHP.

Scripts para grficos estadsticos


Si en algn momento tienes inters en insertar en tus pginas grficos estadsticos, en esta direccinhttp://www.aditus.nu/jpgraph/index.php podrs encontrar una interesante coleccin de scripts listos para usar, con licencia gratuita para usos no comerciales.

Formatos soportados Formatos de imgenes


Aunque podemos obtener desde info.php informacin sobre los tipos de imgenes soportados por la versin en uso de PHP, existe una funcin que permite determinarlos. imagetypes()

Devuelve un campo de bits correspondiente a los formatos soportados por la versin de GD que estamos utilizando. Los formatos de imagen que PHP soporta actualmente son: GIF, JPG, PNG y WBMP. El conocimiento de estas posibilidades grficas puede sernos muy til a la hora de elegir entre los diferentes formatos grficos disponibles. Aqu tienes el cdigo fuente de un fichero que permite obtener informacin sobre los formatos soportados por tu versin de PHP.

Formatos soportados
<?php if (imagetypes() & IMG_GIF) { echo "El tipo GIF es soportado<br>"; }else{ echo "El tipo GIF NO ES SOPORTADO<BR>"; } if (imagetypes() & IMG_PNG) { echo "El tipo PNG es soportado<br>"; }else{ echo "El tipo PNG NO ES SOPORTADO<BR>"; } if (imagetypes() & IMG_JPG) { echo "El tipo JPG es soportado<br>"; }else{ echo "El tipo JPG NO ES SOPORTADO<BR>"; } if (imagetypes() & IMG_WBMP) { echo "El tipo WBMP es soportado<br>"; }else{ echo "El tipo WBMP NO ES SOPORTADO<BR>"; } ?>
ejemplo191.php

Creando imgenes Creacin de imgenes dinmicas


Una imagen dinmica es tan slo un script que contiene las instrucciones para la creacin de esa imagen. Para visualizar una imagen dinmica desde una pgina web basta con invocar el fichero que contiene el script desde la etiqueta clsica de insercin de imgenes de HTML <img src="imgxx.php"> donde imgxx.php ser el nombre del script que genera la imagen.

Primera etiqueta
Una vez conocidos los formatos que soporta nuestra versin, ya podemos generar imgenes utilizando cualquiera de esos formatos. Trabajaremos con dos de ellos: JPG y PNG. La primera instruccin que ha de contener cualquier script que deba generar imgenes ha de ser la siguiente: Header("Content-type: image/jpeg") si se trata de crear una imagen JPG o: Header("Content-type: image/png") si pretendemos que la imagen tenga formato PNG.

Cuidado! Cualquier etiqueta header (cabecera) ha de incluirse obligatoriamente al comienzo del script antes que ninguna otra instruccin y sin ninguna lnea en blanco que la preceda. Pondremos siempre estas instrucciones inmediatamente debajo de <? sin que las separe ninguna lnea en blanco.

Creacin de imgenes
Definida la etiqueta anterior tenemos que: crear la imagen, dibujarla y luego enviarla al navegador para que pueda ser visualizada y, por ltimo, (no es imprescindible pero si muy conveniente) borrarla, con el fin de liberar la memoria del servidor ocupada durante el proceso de generacin de la misma. Estas son las funciones PHP para esos procesos: $nombre = imagecreate(ancho, alto)

Con esta funcin se crea una imagen del tamao indicado en los parmetros ancho y alto (en pixels) que ser recogida en la variable$nombre. Esta funcin es idntica para cualquier formato de imagen.

Envo de imgenes al navegador


Para enviar imgenes al navegador (visualizacin) se usan funciones diferentes segn el tipo de imagen definida en Header. Si pretendemos que la imagen tenga formato JPG habremos puesto en Header la indicacin jpeg (cuidado! observa la sintaxis... jpeg). En este caso la funcin de visualizacin ser: Imagejpeg($nombre)

Si se tratara de una imagen en formato PNG (recuerda que debe estar definido en Header) la sintaxis sera: Imagepng($nombre)

Eliminando imgenes de la memoria


Para borrar imgenes de la memoria del servidor (que no del navegador) se utiliza la siguiente sintaxis: Imagedestroy($nombre)

El primer ejemplo
<?php /* insertamos la cabecera sin ninguna contenido (ni siquiera lnea en blanco) qantes <php */ Header("Content-type: image/jpeg"); /* establecemos las dimensiones de la imagne y la creamos */ $im = imagecreate(200,200); /* mostramos las imagen */ Imagejpeg($im); /* la eliminamos de la memoria */ Imagedestroy($im); ?>
Ver ejemplo192.php

Colores
Creacin de colores
PHP permite crear una paleta de colores. Para ello se pueden crear variables de color (con independencia del formato utilizado) mediante la siguiente funcin: $color=imagecolorallocate ($nombre, rojo, verde, azul)

donde la variable $color recoge el color resultante de mezclar los colores primarios indicados en rojo, verde y azul que sern nmeros enteros comprendidos entre 0 y 255 y que especifican la intensidad de las luces roja, verde y azul utilizadas para la obtencin del color y donde $nombre es la variable utilizada para la creacin de la imagen por imagecreate Se pueden definir tantos colores como se deseen tan slo con utilizar nombres de variables distintos para cada uno de ellos.

Aplicar colores de fondo


Para aplicar un color de fondo a una imagen (no importa el tipo del formato) se utiliza la siguiente funcin: Imagefill($nombre,x,y,$color)

donde $nombre es la variable que contiene la imagen, x e y son las coordenadas del punto de la imagen a partir del cual se aplica el relleno y $color el color (previamente definido) que se pretende aplicar a la imagen. Mediante esta funcin todos los puntos colindantes con el de coordenadas x,y que tengan su mismo color sern rellenados con el color especificado en la variable $color. Aqu tienes dos ejemplos de creacin de una imagen con un color de fondo. Se diferencian nicamente en el formato. La primera ser una imagen JPG y la segunda ser PNG.

<?php Header("Content-type: image/jpeg"); $im = imagecreate(200,200); /* creamos un color de fondo con nombre $fondo */ $fondo=imagecolorallocate ($im, 0, 0, 200); /* aplicamos el clor al fondo */

Imagefill ($im, 0, 0, $fondo); Imagejpeg($im); Imagedestroy($im); ?>


Ver ejemplo193.php

<?php Header("Content-type: image/png"); $im = imagecreate(200,200); /* creamos un color de fondo con nombre $fondo */ $fondo=imagecolorallocate ($im, 0, 0, 200); /* aplicamos el clor al fondo */ Imagefill ($im, 0, 0, $fondo); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo194.php

Figuras
Rectngulos sin relleno
Para dibujar un rectngulo sin relleno (solo las lneas) se utiliza la siguiente funcin: imagerectangle($nombre, x0, y0, x1, y1, $color)

Dnde $nombre es el nombre de la imagen, x0, y0 son las coordenadas del vrtice superior izquierdo y x1, y1 las coordenadas delvrtice inferior derecho y $color el color que pretendemos asignar a los lados del rectngulo. El punto (0,0) siempre es la esquina superior izquierda de la imagen y recuerda que las lneas no tienen un color distinto al del fondo no se visualizar el rectngulo.

<?php Header("Content-type: image/jpeg"); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $linea=imagecolorallocate ($im, 255, 255, 255); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $linea); Imagejpeg($im); Imagedestroy($im); ?>
Ver ejemplo195.php

<?php Header("Content-type: image/png"); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $linea=imagecolorallocate ($im, 255, 255, 255); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $linea); Imagepng($im); Imagedestroy($im); ?>

Ver ejemplo196.php

Rectngulos con relleno


Para dibujar un rectngulo con relleno se utiliza la siguiente funcin: imagefilledrectangle($nombre, x0, y0, x1, y1, $color)

Los parmetros son idnticos a los del caso anterior con la nica diferencia de que en este caso el rectngulo aparecer relleno con el color elegido.

<?php Header("Content-type: image/jpeg"); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); /*aplicamos un color al fondo de la imagen */ Imagefill ($im, 0, 0, $fondo); /* trazamos un rectangulo en blanco */ imagerectangle ($im, 10, 10, 190, 190, $blanco); /* dentro del rectngulo anterior insertamos otro coloreado */ imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); Imagejpeg($im); Imagedestroy($im); ?>
Ver ejemplo197.php

<?php Header("Content-type: image/png"); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); /*aplicamos un color al fondo de la imagen */ Imagefill ($im, 0, 0, $fondo); /* trazamos un rectangulo en blanco */ imagerectangle ($im, 10, 10, 190, 190, $blanco); /* dentro del rectngulo anterior insertamos otro coloreado */ imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo198.php

Polgonos con relleno


Para trazar un polgono con un color de fondo son necesarias dos operaciones: Crear un array con las coordenadas de cada uno de sus vrtices. Aplicar la funcin que dibuja polgonos de este tipo. La creacin del array podra hacerse as: $vertices=(x0, y0, x1, y1,... xn, yn )

dnde se iran introduciendo las coordenadas de los sucesivos vrtices del polgono (x e y de cada vrtice). Una vez creados los vrtices aplicaranos la siguiente funcin: imagefilledpolygon($nombre, $vertices, n vertices , $color)

donde $nombre es el nombre de la imagen, $vertices es el array que contiene las coordenadas de los vrtices, n vertices es el nmero de vrtices del polgono y $color es el color de relleno.

<?php Header("Content-type: image/jpeg"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagefilledpolygon ($im, $esquinas, 4, $blanco); Imagejpeg($im); Imagedestroy($im); ?>
Ver ejemplo199.php

<?php Header("Content-type: image/png"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagefilledpolygon ($im, $esquinas, 4, $blanco); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo200.php

Polgonos sin relleno


Su funcionamiento es idntico al anterior en tanto requiere que se defina el array de coordenadas de los vrtices y los parmetros de la funcin son los mismos indicados en el caso anterior. Slo se modifica el nombre de la funcin que en este caso es: imagepolygon($nombre, $vertices, n vertices , $color)

<?php Header("Content-type: image/jpeg"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $rojo=imagecolorallocate ($im, 255,0, 0); $amarillo=imagecolorallocate ($im, 255, 255,0); Imagefill ($im, 0, 0, $fondo);

imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagepolygon ($im, $esquinas, 4, $rojo); Imagejpeg($im); Imagedestroy($im); ?>
Ver ejemplo201.php

<?php Header("Content-type: image/png"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $rojo=imagecolorallocate ($im, 255,0, 0); $amarillo=imagecolorallocate ($im, 255, 255,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagepolygon ($im, $esquinas, 4, $rojo); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo202.php

Elipses, circunferencias y arcos


Mediante una nica funcin podremos dibujar elipses, circunferencias y arcos. Es la siguiente: imagearc($nom, Xcentro, Ycentro , a, b, anguloinicial, angulofinal, $color)

Los parmetros de esta funcin son los siguientes: $nombre es el nombre de la imagen. Xcentro e Ycentro las coordenadas del centro de la elipse o circunferencia. a es la longitud del semieje horizontal de la elipse. b es la longitud del semieje vertical de la elipse. anguloinicial es la posicin angular del radio inicial del arco y se expresa en grados sexagesimales. angulofinal es la posicin angular del radio final del arco tambin en grados sexagesimales. $color es el color con el que se dibujar la lnea. Respecto a los ngulos, CERO GRADOS coincide con el cero trigonomtrico pero el sentido es contrario, es decir, el de las agujas del reloj. Obviamente, para dibujar una circunferencia basta con hacer iguales los valores de a y de b y fijar los puntos inicial y final en 0 y 360 respectivamente.

<?php Header("Content-type: image/jpeg"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0);

$rojo=imagecolorallocate ($im, 255, 0,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagepolygon ($im, $esquinas, 4, $blanco); imagearc ($im, 100, 100, 160, 160, 0, 360, $fondo); imagearc ($im, 100, 100, 160, 100, 0, 360, $rojo); imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo); Imagejpeg($im); Imagedestroy($im); ?>
Ver ejemplo203.php

<?php Header("Content-type: image/png"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreate(200,200); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); $rojo=imagecolorallocate ($im, 255, 0,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagepolygon ($im, $esquinas, 4, $blanco); imagearc ($im, 100, 100, 160, 160, 0, 360, $fondo); imagearc ($im, 100, 100, 160, 100, 0, 360, $rojo); imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo204.php

Dibujando sobre una imagen de fondo


PHP permite crear imgenes utilizando como fondo una prEexistente. Para ello es necesario cambiar la instruccin $nom = imagecreate(x,y) por $nom= imagecreatefrompng (nombre_de_la_imagen_de_fondo) si se trata de utilizar una imagen con formato PNG o$nom= imagecreatefromjpeg (nombre_de_la_imagen_de_fondo) cuando se trata de usar una imagen JPG. La imagen resultante puede tener formato JPG o PNG dependiendo de lo que se especifique en Header y como formato de salida independientemente del formato que pudiera tener la imagen utilizada como fondo de la composicin

<?php Header("Content-type: image/jpeg"); $esquinas=array(20,100,100,180,180,100,100,20); $im = imagecreatefrompng('./images/cruz.png'); $fondo=imagecolorallocate ($im, 0, 0, 200); $blanco=imagecolorallocate ($im, 255, 255, 255); $amarillo=imagecolorallocate ($im, 255, 255,0); $rojo=imagecolorallocate ($im, 255, 0,0); Imagefill ($im, 0, 0, $fondo); imagerectangle ($im, 10, 10, 190, 190, $blanco); imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo); imagepolygon ($im, $esquinas, 4, $blanco); imagearc ($im, 100, 100, 160, 160, 0, 360, $fondo); imagearc ($im, 100, 100, 160, 100, 0, 360, $rojo); imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo); Imagejpeg($im); Imagedestroy($im); ?>

Ver ejemplo204a.php Imagen original PNG Imagen resultante JPG

Como puedes comprobar en los ejemplos, el tamao de la imagen es el mismo de la utilizada como fondo.

Guardando imgenes
Las imgenes que son creadas mediante la sintaxis anterior no se guardan en el servidor. Si se pretendiera guardarlas, hay que modificar la sintaxis de las etiquetas: Imagepng($nombre) o Imagejpeg($nombre) aadiendo un segundo parmetro con el nombre y la extensin del fichero que vamos de guardar. As por ejemplo: Imagepng($nombre, "mi_imagen.png") o Imagejpeg($nombre, "mi_imagen.jpg") guardaran en el servidor las imgenes creadas con los nombres mi_imagen.png o mi_imagen.jpg en el directorio actual del servidor.>

Cuidado! No dejes NUNCA lneas en blanco entre la etiqueta <? de comienzo del script y la lnea que contiene Header Si escribiramos el script anterior sustituyendo image/jpeg por image/png e Imagejpeg($im) por Imagepng($im)no visualizaramos nada. El formato jpg a falta de especificaciones considera la imagen con negro como color de fondo, pero png requiere que ese color sea especificado.

Utilizacin de imgenes dinmicas


En todos los ejemplos anteriores hemos podido visualizar las imgenes con slo llamarlas desde el navegador, de la misma forma que podramos visualizar cualquier otra imagen. Pero las imgenes dinmicas pueden ser insertadas en una pgina web de la misma forma que cualquier otra imagen. Aqu tienes un ejemplo donde se recogen en una pgina web todas las imgenes dinmicas creadas anteriormente.
ejemplo205.php Ver cdigo fuente

Si observas el cdigo fuente vers que es exactamente el mismo que se utiliza para insertar una imagen normal, con la nica diferencia de que aqu el nombre de la imagen ser el mismo que el del script PHP que la genera.

Imgenes con lneas y textos Trazando segmentos


La funcin PHP que permite dibujar segmentos rectilneos es la siguiente: imageline($nombre, x0, y0, x1,y1,$color)

donde: $nombre es el nombre de la variable definida mediante imagecreate, x0 e y0 son las coordenadas de uno de los extremos; x1e y1 son las coordenadas del otro extremo y $color es la variable de color con el que ser dibujada la lnea. Tal como puedes observar en los primeros ejemplos de esta pgina, PHP utiliza como fondo de la imagen el primer color definido por la funcin: ImageColorAllocate. Esta opcin de PHP nos obliga a definir dos colores distintos para conseguir la visibilidad de las lneas.

Aunque presentaremos nicamente el cdigo fuente de una de las imgenes, para hacer la comprobacin de las funciones y las diferencias de visualizacin insertaremos dos ejemplos, uno en formato PGN y otro en JPG. Recuerda que las nicas diferencias entre ambos radican en utilizar: Header("Content-type: image/png") o Header("Contenttype: image/jpeg") y en las funciones Imagepng Imagejpeg.

<?php Header("Content-type: image/png"); $im = imagecreate(200,200); $fondo=ImageColorAllocate ($im,0,0,255); $linea=ImageColorAllocate ($im,255,255,255); imageline($im,0,0,200,200,$linea); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo211.php Formato PNG Ver ejemplo212.php Formato JPG

Crear transparencias
Si deseamos que un color determinado se comporte como si fuera transparente debemos utilizar la funcin: imagecolortransparent ($nombre ,$color).

donde: $nombre es el nombre de la variable definida mediante imagecreate, y $color es el color que pretendemos hacer transparente. No olvides estos dos pequeos detalles: Si pretendes lograr un fondo transparente debes hacer transparente el primero de los colores definidos. Esta funcin slo tiene sentido en imgenes PNG que son las nicas que permiten zonas transparentes. Recuerda que JPG no las permite.

<?php Header("Content-type: image/png"); $im = imagecreate(200,200); $fondo=ImageColorAllocate ($im,0,0,255); $linea=ImageColorAllocate ($im,255,0,0); imagecolortransparent ($im ,$fondo); imageline($im,0,0,200,200,$linea); Imagepng($im); Imagedestroy($im); ?>
Ver ejemplo213.php Formato PNG Ver ejemplo214.php Formato JPG

Insertando textos
Para insertar textos dentro de una imagen hemos de recurrir a una de estas funciones: imagechar ($imagen, tamao, x, y, $texto, $color)

Requiere que la variable $texto contenga una cadena definida con anterioridad. Mediante esta funcin se inserta el primer carcter de la cadena con orientacin horizontal. Los parmetros de la funcin son los siguientes: $nombre el nombre de la variable con la que fue definida por imagecreate tamao es un nmero comprendido entre UNO y CINCO que asigna el tamao de la letra de menor a mayor. x e y son las coordenadas del punto donde se colocar la esquina superior izquierda del carcter a representar. $texto es la cadena de texto de la que se extraer el primer carcter, el nico que se ver en la imagen. $color es el color del carcter a representar.

<?php Header("Content-type: image/png"); $im = imagecreate(150,150); $t1="Tamao 1"; $t2="Tamao 2"; $t3="Tamao 3"; $t4="Tamao 4"; $t5="Tamao 5"; $fondo=imagecolorallocate ($im, 0, 0, 200); $amarillo=imagecolorallocate ($im, 255, 255,0); imagechar ($im, 1, 0, 0, $t1, $amarillo); imagechar ($im, 2, 20, 20, $t2, $amarillo); imagechar ($im, 3, 40, 40, $t2, $amarillo); imagechar ($im, 4, 60, 60, $t2, $amarillo); imagechar ($im, 5, 80, 80, $t2, $amarillo); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo216.php Formato PNG Ver ejemplo217.php Formato JPG

imagecharup ($imagen, tamao, x, y, $texto, $color)

Su funcionamiento es similar al de la funcin anterior, con la nica diferencia de que inserta el carcter con orientacin vertical. Lascoordenadas de insercin tambin se corresponden con las de la esquina superior izquierda del carcter pero, recuerda que ahora estar girado y que, por lo tanto, ese punto coincidir con parte inferior izquierda de la imagen del carcter.

<?php Header("Content-type: image/png"); $im = imagecreate(150,150); $t1="Tamao 1"; $t2="Tamao 2"; $t3="Tamao 3"; $t4="Tamao 4"; $t5="Tamao 5"; $fondo=imagecolorallocate ($im, 0, 0, 200); $amarillo=imagecolorallocate ($im, 255, 255,0); imagecharup ($im, 1, 10, 10, $t1, $amarillo); imagecharup ($im, 2, 20, 20, $t2, $amarillo); imagecharup ($im, 3, 40, 40, $t2, $amarillo); imagecharup ($im, 4, 60, 60, $t2, $amarillo); imagecharup ($im, 5, 80, 80, $t2, $amarillo); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo218.php Formato PNG Ver ejemplo219.php Formato JPG

imagestring ($imagen, tamao, x, y, $texto, $color)

Esta funcin se comporta de forma similar a imagechar. La nica diferencia entre ambas es que mientras imagechar inserta slo el primer carcter, en el caso de imagestring se inserta la cadena completa. Los parmetros de ambas funciones son los mismos. Si la cadena desborda los lmites de la imagen slo se visualizar la parte de la misma contenida dentro de stos.

<?php Header("Content-type: image/png"); $im = imagecreate(150,150); $t1="Tamao 1"; $t2="Tamao 2"; $t3="Tamao 3"; $t4="Tamao 4"; $t5="Tamao 5"; $fondo=imagecolorallocate ($im, 0, 0, 200); $amarillo=imagecolorallocate ($im, 255, 255,0); imagestring ($im, 1, 10, 20, $t1, $amarillo); imagestring ($im, 2, 10, 40, $t2, $amarillo); imagestring ($im, 3, 10, 60, $t3, $amarillo); imagestring ($im, 4, 10, 80, $t4, $amarillo); imagestring ($im, 5, 10, 100, $t5, $amarillo); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo220.php Formato PNG Ver ejemplo221.php Formato JPG

imagestringup ($imagen, tamao, x, y, $texto, $color)

Inserta una cadena completa con orientacin vertical y sus parmetros son idnticos a los comentados cuando nos hemos referido aimagecharup.

<?php Header("Content-type: image/png"); $im = imagecreate(150,150); $t1="Tamao 1"; $t2="Tamao 2"; $t3="Tamao 3"; $t4="Tamao 4"; $t5="Tamao 5"; $fondo=imagecolorallocate ($im, 0, 0, 200); $amarillo=imagecolorallocate ($im, 255, 255,0); imagestringup ($im, 1, 10, 100, $t1, $amarillo); imagestringup ($im, 2, 20, 100, $t2, $amarillo); imagestringup ($im, 3, 40, 100, $t3, $amarillo); imagestringup ($im, 4, 60, 100, $t4, $amarillo); imagestringup ($im, 5, 80, 100, $t5, $amarillo); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo222.php Formato PNG Ver ejemplo223.php Formato JPG

Tipos de letra
Todas las funciones anteriores utilizan siempre la fuente predefinida por PHP y slo permiten los cinco tamaos que hemos podido ver en los ejemplos. Afortunadamente lo veremos en la pgina siguiente PHP tambin permite usar fuentes TrueType y aplicarlas en la creacin de imgenes.

Manejando fuentes Utilizando fuentes TrueType


Si has ledo los comentarios de la pgina anterior recordars que para usar estas funciones es preciso que estn instaladas las libreras FreeType y que, adems, conozcamos el path de directorio que contiene las fuentes TrueType. Hemos creado un subdirectorio llamado fuentes y lo hemos incluido en directorio donde estn alojadas estas pginas. En ese subdirectorio hemos incluido dos fuentes TrueType manteniendo en una de ellas el nombre original (arial.ttf) y renombrado la otra comofuente2.ttf. Como podrs comprobar en los ejemplos, no hay problema alguno por el hecho de renombrar las fuentes.

Escribiendo con fuentes TrueType


La funcin PHP que nos permite insertar este tipo de textos en imgenes dinmicas es la siguiente: Imagettftext($nombre, tamao, angulo, x, y, $color, $fuente, $texto)

donde: $nombre es, como siempre, el nombre de la imagen. tamao es un nmero entero que indica el el tamao de la fuente. angulo es el giro expresado en grados sexagesimales que pretendemos que tenga la cadena de texto. Si ang=0 el texto aparecer escrito en horizontal. x e y son las coordenadas del punto de inicio de la insercin del texto. Ese punto coincide con la esquina inferior izquierda del rectngulo imaginario que contiene el texto. $color es el color a utilizar en el texto. fuente es una cadena de texto que contiene el path y el nombre de la fuente. Observa los ejemplos. $texto es el nombre de la variable que contiene el texto a insertar.

Texto True Type horizontal


<?php Header("Content-type: image/png"); $im = imagecreate(400,300); $fondo=imagecolorallocate ($im, 255, 255, 210); $rojo=imagecolorallocate ($im, 255, 0, 0); $texto="PHP"; Imagettftext($im, 40, 0, 100, 270, $rojo,"./fuentes/fuente2.ttf", $texto); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo224.php Formato PNG Ver ejemplo225.php Formato JPG

Texto True Type girado


<?php Header("Content-type: image/png"); $im = imagecreate(400,300); $fondo=imagecolorallocate ($im, 255, 255, 210); $rojo=imagecolorallocate ($im, 255, 0, 0); $texto="Me gusta PHP"; Imagettftext($im, 40, 30, 100, 270, $rojo, "./fuentes/fuente2.ttf", $texto); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo226.php Formato PNG Ver ejemplo227.php Formato JPG

Cuidado! Las rutas (path) de la las fuentes utilizadas por Imagettftext pueden darte un montn de quebraderos de cabeza. Las rutas relativas que ves en estos ejemplos no parecen dar problema alguno. Sin embargo si hiciramos algo como crear una variable previa del tipo: $ruta="fuentes"; y luego sustituir "./fuentes/fuente2.ttf" por: "./". $ruta."/fuente2.ttf" que aparentemente da el mismo resultado ./fuentes/fuente2.ttf se nos genera un error de fuente no encontrada. La solucin que parece ser ms efectiva es huir como alma que lleva el diablo del uso de variables en la asignacin de rutas de las fuentes. Vamos, escribir la ruta completa a pico y pala!

Colocando los textos


PHP dispone de una funcin que permite determinar las dimensiones de una caja de texto (el rectngulo imaginario que rodea el texto). $rect= ImageTTFBBox (tamao, angulo, fuente, $texto) donde tamao es el tamao de la fuente a utilizar, angulo es el ngulo de rotacin del texto que tendra valor cero en el caso de orientacin horizontal, fuente es el path y nombre de la fuente a a utilizar, $texto es el nombre de la variable que contiene el texto a incluir.

La variable $rect recoge un array escalar cuyos valores son las coordenadas de las cuatro esquinas de la caja de texto. Los ndices correspondientes a cada uno de los elementos de ese array son los siguientes: Inferior izquierdo. Sus coordenadas son: $rect[0] y $rect[1] Inferior derecho. Sus coordenadas son: $rect[2] y $rect[3] Superior derecho. Sus coordenadas son: $rect[4] y $rect[5] Superior izquierdo. Sus coordenadas son: $rect[6] y $rect[7] Respecto a estas coordenadas, habremos de tener en cuenta lo siguiente: Las correspondientes al vrtice inferior izquierdo son siempre (0,0). Los puntos situados por encima del (0,0) tienen ordenada negativa. Las abscisas de los puntos situados a la izquierda del (0,0) son negativas.

Centrando textos
Aqu tienes un ejemplo donde utilizando ImageTTFBox e ImageTTFText se puede centrar un texto -tanto si es horizontal como si est girado- con relacin a un punto. En este ejemplo, el punto de referencia para el centrado es (200,150) que es el centro de la imagen. Las coordenadas de ImageTTFText, como puedes ver, estn calculadas usando las coordenadas de ese punto de referencia y los valores del array generado por ImageTTFBox. Si la variable que contiene el array generado por ImageTTFBox se llama $pepa, las coordenadas del centro del rectngulo imaginarioson $pepa[4]/2 y $pepa[5]/2. Partiendo de esos valores, si queremos centrar el texto sobre un punto de la imagen cuyas coordenadas son (X,Y) nos basta con escribir como parmetros de la funcin ImageTTFText los siguientes: Abscisa= X - $pepa[4]/2 Ordenada= Y - $pepa[5]/2 Este procedimiento es vlido tanto para textos horizontales como para textos girados.

<?php Header("Content-type: image/png"); $im = imagecreate(400,300); $fondo=imagecolorallocate ($im, 255, 255, 210); $gris=imagecolorallocate ($im, 160, 160,160); $rojo=imagecolorallocate ($im, 255, 0, 0); $texto="El mundo del PHP"; $texto1="lleno de posibilidades"; $marco= ImageTTFBBox (40, 0, "./fuentes/arial.ttf", $texto); Imagettftext($im,40,0,200-$marco[4]/2,150-$marco[5]/2, $gris,"./fuentes/arial.ttf",$texto); $marco1= ImageTTFBBox (30, 30, "./fuentes/fuente2.ttf", $texto1); Imagettftext($im,30,30,200-$marco1[4]/2,150-$marco1[5]/2,$rojo,"./fuentes/fuente2.ttf", $texto1); Imagepng($im); imagedestroy($im); ?>
Ver ejemplo228.php Formato PNG Ver ejemplo229.php Formato JPG

Un ejemplo resumen

Aqu tienes un ejemplo bastante completo de generacin de imgenes dinmicas.


Ver ejemplo230.php Ver cdigo fuente

Diagramas de sectores Diagramas de sectores


Esta posibilidad grfica de tratamiento de informacin estadstica la proporciona la funcin

imagefilledarc( Xc, Yc, a, b,anguloi, angulof , $color, tipo )

dnde los parmetros son: Xc y Yc que son las coordenadas del centro de la elipse cuyo arco (o porcin) tratamos de representar. Los nmeros a y b son las longitudes (expresadas en pixels) de los semiejes horizontal y vertical de la elipse. Si ambos fueran iguales el resultado sera circular. Los parmetros anguloi y angulof son las posiciones (en grados sexagesimales) de los radios (inicial y final) que delimitan el sector que se trata de representar. Los cero grados coinciden con el semieje horizontal positivo y el sentido del recorrido angular es el de las agujas del reloj. El parmetro $color es la variable ha de ser definida previamente mediante imagecolorallocate que indica el color que ha de utilizarse en el grfico. Por ltimo el parmetro tipo un constante PHP que puede tomar uno de los siguientes valores: IMG_ARC_PIE,IMG_ARC_NOFILL, IMG_ARC_EDGED o IMG_ARC_CHORD Con la primera de las constantes dibuja el sector de elipse delimitado por los radios indicados relleno con el color especificado. Mediante IMG_ARC_NOFILL nicamente dibuja la porcin de arco, pero no incluye la representacin de los radios en el dibujo. La opcionIMG_ARC_EDGED se comporta de forma idntica a IMG_ARC_PIE cuando se utiliza de forma aislada aunque tiene una opcin muy interesante que veremos un poco ms abajo. Con IMG_ARC_CHORD el resultado es un tringulo relleno con el color indicado formado por los dos radios y la cuerda correspondiente al arco que delimitan.

Combinar dos constantes de tipo


Cuando en la funcin imagefilledarc() utilizamos como tipo una expresin tal como: IMG_ARC_NOFILL|IMG_ARC_EDGED (fjate en el signo | que separa ambas constantes) lo que obtenemos es la representacin grfica del contorno del sector (incluye los radios que lo delimitan). Mediante esta opcin -con dos llamadas a la funcin- tenemos la posibilidad de representar el sector con un color de relleno (usando IMG_ARC_PIE) y, luego, superponerle un contorno de distinto color. Puedes verlo en los ejemplos.

Efecto tridimensional
Tal como puedes ver en los ejemplos, resulta fcil lograr un efecto tridimensional en el dibujo de los sectores. Basta con crear un bucle que dibuje arcos sucesivos (separados verticalmente por un pixel) y posteriormente superponer un sector relleno con un color distinto.

Ejemplos de sectores
<?php $im = imagecreate (400, 400); $fondo = imagecolorallocate($im, 226, 226, 226); $col1=imagecolorallocate($im,255,255,0); $col2=imagecolorallocate($im,255,0,0); imagefilledarc($im, 200, 200, 350, 300, 20, 240, $col1, IMG_ARC_PIE); imagefilledarc($im, 200, 200, 350, 300, 10, 150, $col2, IMG_ARC_NOFILL); header('Content-type: image/png'); imagepng($im); imagedestroy($im); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<?php $im = imagecreate (400, 400); $fondo = imagecolorallocate($im, 226, 226, 226); $col1=imagecolorallocate($im,255,255,0); $col2=imagecolorallocate($im,255,0,0); imagefilledarc($im, 200, 200, 350, 300, 20, 240, $col1, IMG_ARC_EDGED); imagefilledarc($im, 200, 200, 350, 300, 10, 150, $col2, IMG_ARC_NOFILL); header('Content-type: image/png'); imagepng($im); imagedestroy($im); ?>

Ver ejemplo .jpg

Ver ejemplo .png

Ver ejemplo .gif

<?php $im = imagecreate (400, 400); $fondo = imagecolorallocate($im, 226, 226, 226); $color1=imagecolorallocate($im,255,0,0); imagefilledarc ($im, 200, 200, 350, 300, 20, 240, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); header('Content-type: image/gif'); imagegif($im); imagedestroy($im); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<?php $im = imagecreate (400, 400); $fondo = imagecolorallocate($im, 226, 226, 226); $color1=imagecolorallocate($im,255,0,0); imagefilledarc ($im, 200, 200, 350, 300, 50, 200, $color1, IMG_ARC_CHORD); header('Content-type: image/gif'); imagegif($im); imagedestroy($im); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<? $im = imagecreate (400, 400); $fondo = imagecolorallocate($im, 226, 226, 226); $color1=imagecolorallocate($im,200,0,0); $color2=imagecolorallocate($im,255,0,0); $color3=imagecolorallocate($im,255,255,255); for($i=200;$i<225;$i++){ imagefilledarc($im, 200, $i, 370, 270, 50, 330, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); } imagefilledarc($im, 200, 200, 370, 270, 50, 330, $color2, IMG_ARC_EDGED); imagefilledarc($im, 200,200, 370, 270, 50, 330, $color3, IMG_ARC_NOFILL|IMG_ARC_EDGED); header('Content-type: image/gif'); imagegif($im); imagedestroy($im); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Encuadre y redimensionado de imgenes Lectura de imgenes externas


La visualizacin de imgenes no presenta ningn problema lo hacemos habitualmente mediante etiquetas HTML cuando se encuentran en el espacio del servidor, bien sea propio o ajeno. El problema puede surgir cuando tratemos de almacenar esas imgenes fuera del root del servidor (una forma de impedir la accesibilidad desde otras webs) y eso puede conseguirse mediante las funciones que veremos en este captulo.

Se trata de utilizar PHP para hacer una copia de la imagen original. Para ello debemos conocer la ubicacin de aquella y tambin sufomato. A partir de esos datos ya solo nos quedara utilizar una de las funciones: $copia=imagecreatefromjpeg($original) o $copia=imagecreatefrompng($original) o $copia=imagecreatefromgif($original)

que nos permitira crear una copia de la imagen original utilizando la funcin adecuada al formato de aquella (jpg, png o gif). La visualizacin de la imagen requiere los mismos elementos de ejemplos anteriores: Header puede incluir como Content-type cualquiera de los valores: image/jpeg, image/png o image/gif imagecreate que ahora requerira una de las opciones imagecreatefromjpeg, imagecreatefrompng imagecreatefromgif segn sea el formato de la imagen original. image..($copia) que ahora requerira una de las opciones imagejpeg($copia), imagepng($copia) imagegif($copia) segn sea el formato establecido en Header. En estos ejemplos puedes ver los resultados de la copia de los tres tipos de imagen.

<?php /* ruta completa hasta la imagen original. Aunque aqui usamos DOCUMENT_ROOT para establecer la ruta hasta la imagen ejemplo no sera preciso que estuviera en el root del servidor. Podra estar en cualquier directorio fuera de ese mbito */ $original=$_SERVER['DOCUMENT_ROOT']."/php/images/caballos.jpg"; /* para conocer el formato de la imagen podemos extraer el nombre de la extensin de la imagen original que ser lo que hay a partir del ltimo "punto" de la cadena que contiene la ruta completa */ for($i=strlen($original)-1;$i>0;$i--){ if (substr($original,$i,1)=="."){ $tipo=substr($original,$i+1); break; } } /* insertamos el Header correspondiente al cualquiera de los tipos de imagen utilizables por PHP. Por ejemplo: jpeg */ Header("Content-type:image/jpeg"); /* el uso de switch puede sernos til para elegir la funcin adecuada */ switch($tipo){ case "jpg": $copia=imagecreatefromjpeg($original); break; case "png": $copia=imagecreatefrompng($original); break; case "gif": $copia=imagecreatefromgif($original); break; } /* visualizamos la imagen ateniendonos al formato establecido en Header */ imagejpeg($copia); /* eliminamos la imagen de memoria */ ImageDestroy($copia); ?>

Ver ejemplo .jpg

Ver ejemplo .png

Ver ejemplo .gif

Redimensionar y recortar de imgenes externas


Puede parecer que esta posibilidad carece de utilidad. A fin de cuentas, con etiquetas HTML podemos asignar el ancho y el alto de una imagen. Pero enseguida veremos que esta opcin no es tan trivial como parece. El objetivo es obtener una imagen con unas dimensiones determinadas y unos mrgenes tambin establecidos a partir de una parte (o el todo) de un original.

Copia de la imagen original. Pretendemos recortar la parte marcada

La imagen resultante tiene bordes en blanco y adems contiene el recorte de la anterior ampliado y deformado

Lo que necesitamos es crear una imagen en blanco con las dimensiones elegidas y posteriormente incrustar en ella la copia de una imagen externa despus de haberla deformado para adaptarla a unas nuevas dimensiones. Para lograr este propsito va a ser necesario que utilicemos estas funciones: $dimensiones=getimagesize($original)

dnde $original es la variable que contiene el path y nombre del fichero externo que contiene la imagen y $dimensiones es un array escalar que contiene las dimensiones de la imagen analizada. El elemento del array $dimensiones[0] contiene el ancho y $dimensiones[1] el alto, ambos expresados en pixels. $ampliacion=imagecreatetruecolor(x, y)

dnde $ampliacion es el identificador de una nueva imagen en blanco creada en color verdadero con dimensiones x e y imagecopyresampled($ampliacion, $copia, Xampliacion, Yampliacion, Xcopia, Ycopia, Ax , Ay, Ox , Oy)

$ampliacion que es el identificador de la imagen destino, es decir la imagen en blanco sobre la que pretendemos insertar todo o parte de la original, $copia es el identificador de una copia de la imagen original previamente guardada en memoria, Xampliacion e Yampliacion son las coordenadas de un punto situado en la esquina superior izquierda del papel a partir del que queremos que se impresione la fotografa. Si queremos una foto a sangre pondremos 0,0 y, si quieres dejar mrgenes en blanco, habr que poner los anchos de esos mrgenes (izquierdo y superior) respectivamente. Xcopia e Ycopia nos servirn para reencuadrar la foto original recortando por la izquierda y por arriba, respectivamente, los anchos que se indiquen aqu en pixels. Si no queremos recortar la imagen original ni por la izquierda ni por la derecha pondremos 0,0.

Ax y Ay indican el ancho y el alto (por este orden) que va a tener la mancha de imagen en la imagen resultante. Ten en cuenta que no podemos salirnos del papel as que esos valores sumados con los mrgenes (izquierdo y superior) no podrn ser mayores que las dimensiones de la imagen ampliada. Ox y Oy indican el ancho y el alto de la porcin del original que tratamos de reproducir. Sumados con Xcopia e Ycopia no pueden exceder el tamao de la imagen original. Con estos parmetros la funcin ya se encarga de redimensionar la imagen (incluso distorsionarla, si no hay proporcionalidad entre los anchos y altos del original y del soporte. El proceso es el siguiente: Hacemos un copia en memoria de la imagen original Creamos una nueva imagen en blanco que ser la imagen resultante Insertamos en la nueva imagen el resultado de la transformacin de la copia de la original

Cuidado! Observa que las imgenes en formato png se visualizan con deficiencias en los bordes de las reas transparentes. Con el mtodo que vemos a continuacin ese problema se reduce considerablemente.

Lectura y redimensionado de imgenes externas


<?php /* indicamos la ruta de la imagen original */ $original=$_SERVER['DOCUMENT_ROOT']."/php/images/caballos.jpg"; /* determinamos el formato de esa imagen */ for($i=strlen($original)-1;$i>0;$i--){ if (substr($original,$i,1)=="."){ $tipo=substr($original,$i+1); break; } } /* determinamos las dimesiones de la imagen original */ $tamano=getimagesize($original); $orig_Ancho = $tamano[0]; $orig_Alto =$tamano[1]; /* vamos a tratar de obtener una imagen deformada para ello usaremos factores de ampliacin distintos para para cada uno de los lados. Multiplicaremos por 2 el ancho y por 1.5 el alto */ $ampliacion_X=2; $ampliacion_Y=1.5; /* Pretendemos que la imagen resultante no tenga mrgenes en blanco por tanto sus dimensiones van a ser las del original multiplicado por los factores de ampliacion */ $resultado_Ancho=$orig_Ancho*$ampliacion_X; $resultado_Alto= $orig_Alto*$ampliacion_Y; /* creamos una copia de la imagen original. Debemos elegir la funcion adecuada al tipo de aquella*/ switch($tipo){ case "jpg": $copia=imagecreatefromjpeg($original); break; case "png": $copia=imagecreatefrompng($original); break; case "gif": $copia=imagecreatefromgif($original);

break; } /* insertamos la cabecera de nuestra imagen final ampliada */ Header("Content-type:image/jpeg"); /* creamos una imagen nueva en color verdadero*/ $ampliada=imagecreatetruecolor($resultado_Ancho,$resultado_Alto); /* aplicamos un color de fondo a la nueva imagen para poder visualizar que incluye la transparencia del png y/o del gif */ if($tipo=="png" OR $tipo=="gif"){ $fondo=imagecolorAllocate($ampliada,255,255,200); imagefill($ampliada,0,0,$fondo); } /* incrustamos la imagen importada sobre la que acabamos de crear teniendo en cuenta los parmetros de la funcin. Los cuatro ceros se deben a que vamos a colocar toda la imagen original (sin recortes) sin dejar ningun margen en blanco) y los anchos y altos se mantienen dado que ni recortamos nada la imagen original ni vamos a dejar margen alguno en la resultante */ imagecopyresampled($ampliada,$copia,0,0,0,0, $resultado_Ancho, $resultado_Alto, $orig_Ancho,$orig_Alto); /* visualizamos la imagen resultante */ imagejpeg($ampliada); ImageDestroy(); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Observa que tanto en el ejemplo anterior como en el siguiente solo hemos utilizado la extensin de la imagen original para elegir la funcin imagecreatefrom.... En el Header hemos puesto image/jpeg y, como es obvio, hemos utilizado la funcin asociada a este formato (imagejpeg). Si sustituimos ambos valores por los correspondientes a otro formato (gif, png) obtendramos resultados similares.

Recortar y encuadrar imgenes externas


<?php /* indicamos la ruta de la imagen original */ $original=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones4.jpg"; /* determinamos el formato de esa imagen */ for($i=strlen($original)-1;$i>0;$i--){ if (substr($original,$i,1)=="."){ $tipo=substr($original,$i+1); break; } } /* determinamos el tamao de la imagen original */ $tamano=getimagesize($original); $orig_Ancho = $tamano[0]; $orig_Alto =$tamano[1]; /* asignamos a una variable el margen en blanco de la imagen igual por los cuatro lados */ $margen=15; /* establecemos los recortes para reencuadrar la imagen original */ $recorte_izq=50; $recorte_sup=80; $recorte_der=40; $recorte_inf=60; /* calculamos las dimensiones para utilizar como parmetros en la funcion imagecopyresampled ancho y alto de la imagen original despus del recorte de encuadre */ $Ancho_recortado=$orig_Ancho-$recorte_izq-$recorte_der; $Alto_recortado=$orig_Alto-$recorte_sup-$recorte_inf; /* establecemos factores de ampliacin iguales para evitar distorsiones */ $ampliacion_X=1.3; $ampliacion_Y=1.3;

/* determinamos las dimensiones de la imagen final teniendo en cuenta los margenes y los factores de ampliacin */ $papel_Ancho=$Ancho_recortado*$ampliacion_X+ 2*$margen; $papel_Alto=$Alto_recortado*$ampliacion_Y+2*$margen; /* dimensiones del area impresa de la imagen resultante Hay que descontar los mrgenes al tamao de la imagen */ $resultado_Ancho=$papel_Ancho -2*$margen; $resultado_Alto=$papel_Alto -2*$margen; switch($tipo){ case "jpg": $copia=imagecreatefromjpeg($original); break; case "png": $copia=imagecreatefrompng($original); break; case "gif": $copia=imagecreatefromgif($original); break; } /* creamos la cabecera de la nueva imagen */ Header("Content-type:image/jpeg"); /* creamos la imagen final asignandole sus dimensiones */ $ampliada=imagecreatetruecolor($papel_Ancho,$papel_Alto); /*ponemos un color de fondo (rojo) que ser con el que se visualizarn los mrgenes*/ $fondo=imagecolorAllocate($ampliada,255,0,0); /* aplicamos el color de fondo */ imagefill($ampliada,0,0,$fondo); /* incrustamos la imagen */ imagecopyresampled($ampliada,$copia,$margen,$margen, $recorte_izq,$recorte_sup, $resultado_Ancho,$resultado_Alto, $Ancho_recortado,$Alto_recortado); /* visualizamos el resultado */ imagejpeg($ampliada); ImageDestroy(); ?>
Ver imgenes original y resultante

Superponer, rotar y dar transparencia a imgenes Colores con transparencia


PHP permite crear colores con transparencia. Para ello se utiliza la funcin: ImageColorAllocateAlpha($imagen, rojo, verde, azul, transparencia)

donde $imagen es el identificador de la imagen que ha sido creada previamente, rojo, verde, azul que son valores numricos (o variables) que contienen en una escala de 0 a 255 la intensidad luminosa de cada uno de los tres colores primarios y transparencia es un valor numrico comprendido entre 0 y 127 que indica el grado de transparencia de la tinta. El valor 0 indica opacidad total, mientras que 127 establece la transparencia total de ese color. En el ejemplhemos incluido dos escalas de transparencias superpuestas a intervalos del 10% (desde 0 hasta 100%) transformados a la escala 0-127.

El orden de superposicin similar a las capas de otros programas grficos se corresponde con el orden de las instrucciones de creacin. Los resultados de las ltimas funciones se superponen siempre a los obtenidos como consecuencia de la ejecucin de las anteriores.

<?php /* Creamos una imagen en color verdadero, le aplicamos un color de fondo (para evitar el negro por defecto) y creamos un nuevo color que utilizaremos para los bordes de rectangulos posteriores*/ Header("Content-type:image/jpeg"); $im_base=imagecreatetruecolor(610,140); $fondo=imagecolorAllocate($im_base,255,255,200); $negro=imagecolorAllocate($im_base,0,0,0); imagefill($im_base,0,0,$fondo); # definimos las componentes de un nuevo color $R=255; $G=00; $B=00; /* vamos a construir una escala de transparencias de 0 a 10 que correspondera con valores de transparencia de 0% al 100%. Crearemos un bucle que dibuje rectangulos rellenos con el color definido en la variable trans que ir aplicando al color bsico los diferentes grados de transparencia y le pondremos un contorno negro para encuadrarlos*/ for($i=0;$i<=10;$i++){ $trans=ImageColorAllocateAlpha($im_base,$R,$G,$B,(int)($i*127/10)); imagefilledrectangle($im_base, 10+55*$i, 20, 50+55*$i, 80, $trans); imagerectangle($im_base, 10+55*$i, 20, 50+55*$i, 80, $negro); } #creamos un nuevo color y repetimos el proceso con nuevos rectangulos #superpuestos a los anteriores y con las transparencias en sentido opuesto # es decir, de 100 a 0% $R=0; $G=0; $B=255; for($i=0;$i<=10;$i++){ $trans=ImageColorAllocateAlpha($im_base,$R,$G,$B,127-(int)($i*127/10)); imagefilledrectangle($im_base, 10+55*$i, 60, 50+55*$i, 120, $trans); imagerectangle($im_base, 10+55*$i, 60, 50+55*$i, 120, $negro); } # visualizamos el resultado imagejpeg($im_base); ImageDestroy(); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Transparencia en imgenes externas


Tambin resulta posible ajustar el grado de transparencia de una imagen externa. Mediante la funcin imagecopymerge($destino, $origen,Xd, Yd, Xf, Yf, Dx, Dy, opacidad)

dnde $destino es el identificador de la imagen sobre la que se va a colocar la transparencia. Como es lgico, deber haber sido creada antes de incluir la funcin. $origen es el identificador de la imagen que pretendemos incluir con un determinado grado de transparencia, Xd e Yd son las coordenadas de un punto situado en la esquina superior izquierda de la imagen destino a partir del que queremos que se impresione la nueva imagen. Si queremos una imagen a sangre pondremos 0,0 y, si quieres dejar mrgenes, habr que poner los anchos de esos mrgenes (izquierdo y superior) respectivamente. Xf e Yf nos servirn para reencuadrar la foto original recortandopor la izquiera y por arriba, respectivamente, los anchos en pixels que aqu se indiquen. Dx y Dy indican el ancho y el alto (por este orden) que va a tener la mancha de imagen. Ten en cuenta que no puedes salirte del papel as que los valores anteriores sumados con los mrgenes que hayas establecido no podrn ser mayores que las dimensiones que has elegido para la imagen destino. Por ltimo, opacidad es un parmetro al que puede asignarse un valor comprendido entre 0 y 100 y representa el porcentaje de opacidad de la imagen superpuesta. Con un valor cien sera totalmente opaca y si fuera cero la transparencia sera total.

<?php # obtener la imagen $original=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones4.jpg"; # buscar el formato de la imagen mediante su extensin for($i=strlen($original)-1;$i>0;$i--){ if (substr($original,$i,1)=="."){ $tipo=substr($original,$i+1); break; } } # tamao del original extraido del array devuelto por getimagesize $tamano=getimagesize($original); $orig_Ancho = $tamano[0]; $orig_Alto =$tamano[1]; # estableceremos un margen en blanco alrededor de la imagen de 10 pixels # igual por los cuatro lados $borde=10; $Ancho=$orig_Ancho+2*$borde; $Alto=$orig_Alto+2*$borde; # creamos la imagen segun el formato original switch($tipo){ case "jpg": $importada=imagecreatefromjpeg($original); break; case "png": $importada=imagecreatefrompng($original); break; case "gif": $importada=imagecreatefromgif($original); break; } Header("Content-type:image/jpeg"); # creamos una imagen nueva, un color de fondo y la rellenamos con l $im_base=imagecreatetruecolor($Ancho,$Alto); $fondo=imagecolorAllocate($im_base,255,255,200); imagefill($im_base,0,0,$fondo); # superponemos la imagen importada posicionandola y aplicandole # una trasmparencia de 50 imagecopymerge( $im_base, $importada, $borde, $borde, 0, 0, $orig_Ancho, $orig_Alto ,50 ); imagejpeg($im_base); ImageDestroy(); ?>
Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Si observas los resultados obtenidos en el ejemplo en el que intentamos dar transparencia a una imagen en formato png podrs observar que deja bastante que desear y produce un efecto indeseado por el recorte de las zonas presuntamente transparentes. Esta situacin nos obliga a replantear la situacin para prever esta circunstancia y recurrir a un truco que parece solventar ese problema. La modificacin del cdigo fuente es la incluimos aqu debajo.

Header("Content-type:image/jpeg"); $im_base=imagecreatetruecolor($Ancho,$Alto); $fondo=imagecolorAllocate($im_base,255,255,200); imagefill($im_base,0,0,$fondo); /* el truco consiste en crear una segunda imagen (im_truco)cuyas dimensiones coincidan con las de la imagen transparente que pretendemos colocar. Le asignamos como color el fondo el mismo

de la imagen destino y hacemos transparente ese color en esa imagen. Despus hacemos una copia de la imagen original sobre la imagen im_truco y sustituimos en la funcin imagecopymerge la imagen original por la obtenida mediante esta chapucilla */ $im_truco=imagecreatetruecolor($orig_Ancho, $orig_Alto); $fondo1=imagecolorAllocate($im_truco,255,0,200); imagefill($im_truco,0,0,$fondo1); imagecolortransparent ($im_truco,$fondo1); imagecopy($im_truco, $importada, 0, 0, 0, 0, $orig_Ancho, $orig_Alto); imagecopymerge( $im_base , $im_truco, $borde , $borde , 0 , 0 ,$orig_Ancho, $orig_Alto ,60 ); imagejpeg($im_base); ImageDestroy();
Ver el nuevo resultado

Montaje de imgenes
Superponer una parte de una imagen
Mediante esta funcin se puede copiar sobre una imagen una parte de otra. Permite extraer porciones de imgenes con su tamao original sin que permita ampliarlas ni reducirlas. Su sintaxis es la siguiente: imagecopy($destino, $original, $x, $y, $X, $Y, $A, $H)

donde: $destino el identificador de la imagen destino, $original el identificador de la imagen original, $x y $y las coordenadas donde se posicionar en la imagen destino la esquina superior izquierda de la porcin copiada, $X y $Y son los anchos de los recortes izquierdo y superior de la imagen a copiar y $A y $H el ancho y el alto del rea de imagen que pretendemos copiar.

<?php /* definimos las imagenes */ $imagen_base=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones1.jpg"; $imagen_superpuesta=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones2.jpg"; Header("Content-type: image/jpeg"); /* creamos en memoria dos imagenes copia de las originales */ $capa_base =imagecreatefromjpeg($imagen_base); $capa_superpuesta =imagecreatefromjpeg($imagen_superpuesta); /* realizamos el montaje de la nueva imagen sobre la base */ imagecopy($capa_base,$capa_superpuesta, 30, 40, 70, 80, 195, 225); /* visualizamos la imagen */ imagejpeg($capa_base); imagedestroy(); ?>
Ver ejemplo

Rotacin de imgenes
Es posible presentar imgenes rotadas por medio de la funcion: imagerotate($imagen,angulo,$fondo)

dnde el parmetro $imagen es el identificador de la imagen a rotar, angulo es el ngulo de rotacin (expresado en grados y tomado en sentido trigonomtrico) y $fondo es un color de fondo asociado a la imagen a rotar que puede ser definido mediante la funcinimagecolorallocate u otra funcin que permita asociar colores a imgenes.

<?php # obtener la imagen $original=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones3.jpg"; for($i=strlen($original)-1;$i>0;$i--){ if (substr($original,$i,1)=="."){ $tipo=substr($original,$i+1); break; } } switch($tipo){ case "jpg": $importada=imagecreatefromjpeg($original); break; case "png": $importada=imagecreatefrompng($original); break; case "gif": $importada=imagecreatefromgif($original); break; } Header("Content-type:image/jpeg"); $fondo=imagecolorallocatealpha($importada,255,255,0,40); $im_base=imagerotate($importada,30,$fondo); imagejpeg($im_base); ImageDestroy(); ?>
Ver ejemplo

Transparencia en capas rotadas


Cuando trabajamos con una imagen truecolor en la que vamos incluyendo en diferentes capas (mediante copy copymerge) otras imgenes recortadas, rotadas, creadas a partir de otra imagen, etc. la transparencia de los colores de los fondos de rotacin no plantea ningn problema. Es suficiente usar la funcin imagecolortransparent, eso s, aplicndola a la imagen correspondiente antes de insertarla mediante la opcin copy en la imagen final.

Cuidado! La funcin imagerotate() no funciona con la versin de la librera GD que se instala con Ubuntu o Debian que es diferente de la que utilizan otras distribuciones de PHP (la de Windows por ejemplo). La forma de resolverlo puedes encontrarla aqu

Ejemplo resumen
Aqu tienes un ejemplo en el que hemos utilizado superposiciones de imgenes, con giros, recortes y diferentes grados de transparencia.
Ver ejemplo resumen Ver codigo fuente

Efectos en imgenes y CAPTCHA Aplicando filtros a imgenes


A partir de PHP 5 se han incluido funciones que permiten aplicar a las imgenes filtros modificadores que producen muchos de los efectos que hasta ahora estaban reservados al software grfico del tipo Gimp o PhotoShop por poner dos ejemplos. Al incluir la funcin: imagefilter ( $imagen , tipo_filtro, param1, param2, ... )

Dnde $imagen es el identificador de imagen, tipo_filtro es un valor numrico entero (o una constante, en cuyo caso no deber su nombre entre comillas) y los parmetros cuyo nmero y valores dependen del tipo de filtro utilizado. Aqu debajo tienes una tabla que contiene los diferentes tipos de filtros disponibles as como los parmetros utilizados por cada uno de ellos.

Imagen original

Imagen transformada

Cdigo fuente

Pulsando en las opciones de la parte inferior podrs visualizar aqu el cdigo fuente de los scripts que transforman la imagen original de acuerdo con los parmetros elegidos para cada opcin

Nombre de la constante

Valor equivalente

Parmetros

Funcin Invierte los colores de la imagen Convertir a escala de grises

Aplicar

IMG_FILTER_NEGATE IMG_FILTER_GRAYSCALE IMG_FILTER_BRIGHTNESS IMG_FILTER_CONTRAST

0 1 2 3
Brillo=60 Contraste=10 Rojo=10 Verde=10

Aplicar Aplicar Aplicar Aplicar

Aumenta o disminuye el brillo en el intervalo 255 a -255 Aumenta o disminuye el contraste en el intervalo 255 a -255

IMG_FILTER_COLORIZE

Azul=10 Alfa=10

Coloriza

Aplicar

IMG_FILTER_EDGEDETECT IMG_FILTER_EMBOSS IMG_FILTER_GAUSSIAN_BLUR IMG_FILTER_SELECTIVE_BLUR IMG_FILTER_MEAN_REMOVAL IMG_FILTER_SMOOTH IMG_FILTER_PIXELATE

5 6 7 8 9 10 11
Suavizado=60 Tamao=5

Detectar y resalta bordes Efecto relieve Desenfoque gaussiano Desenfoque selectivo Aplica efecto boceto a la imagen Aplica suavizado la imagen

Aplicar Aplicar Aplicar Aplicar Aplicar Aplicar Aplicar

Pixelacin avanzada Si

Pixela la imagen (Solo funciona en versiones PHP 5.3 y superiores)

Los filtros requieren incluir los parmetros que aparecen en las respectivas cuadrculas. Su inclusin se realiza agregndolos (nicamente sus valores numricos) a continuacin del nombre o identificador del filtro y separados de este y entre ellos por una coma.

Aplicaciones sucesivas de efectos


Las diferentes opciones de filtrado pueden irse aplicando de forma sucesiva sobre una misma imagen. Un caso tpico puede ser el que puedes verlo en la imagen de la parte superior si pulsas en este enlace. El efecto sepia se logra aplicando primero IMG_FILTER_GRAYSCALE para convertir a escala de grises y colorizando por medio de IMG_FILTER_COLORIZE. En este caso los valora aplicados a las componentes R,G,B han sido 210, 90, 30 respectivamente y el valor del cuarto parmetro (canal alfa) ha sido de 64

Obtencin de valores de las componentes de color


PHP dispone de funcin: $codigo_de_color=imagecolorat($imagen, x, y) por medio de la cual la variable $codigo_de_color recogera un valor decimal resultante de convertir en decimal el color correspondiente (la cadena hexadecimal con el formato clsico RRGGBB) al pixel cuyas coordenadas horizontal y vertical, respecto a la esquina superior izquierda de la imagen son x e y de la imagen cuyo identificador es $imagen Para la manipulacin de imgenes puede resultar muy interesante conocer las componentes R,G y B de esos colores. En caso de la libreria GD cuando se trata de conocer el color de uno de los pixel de una imagen los valores R,G, B de sus componentes puede obtenerse por medio de la funcin: $codigo_de_color=imagecolorat($imagen ,x,y) $array_de_colores=imagecolorsforindex($imagen ,$codigo_de_color)
Ver ejemplo Ver cdigo fuente

Si ejecutas el ejemplo anterior podrs ver que imagecolorsforindex es un array asociativo cuyos indices son: red, green,blue y alfaque corresponden los tres primeros a las componentes de los colores primarios y el cuarto alfa que indicara el grado de transparencia de ese color (en caso de que la imagen la tuviera asignada). Por lo general la informacin de color de un pixel de una imagen estara conformado por 24 bits de los cuales corresponden 8 a cada uno de ellos. Cuando se agrega un canal alfa para incluir una determinada transparencia se agregan otros 8 bits para recoger este valor. En ese caso, como resulta obvio, se requieren 32 bits por cada pixel. El valor cero asignado en el ejemplo anterior al ndice alfa significa que no est asignada ninguna transparencia al pixel estudiado. Cuando se trata de extraer, sin disponer de una imagen de referencia, las componentes de color de un cdigo de color uno los procedimientos para hacerlo requiere el uso de los operadores bit a bit de la forma que hemos tratado de desglosar paso a paso en la tabla que tienes aqu debajo.
Valor hexadecima Valor binario l

Valor inicial

Funcin

Valor decimal

Resultado

$a="#ABCDE $b=str_replace('#','',$a)); F" $b=ABCDEF $c=hexdec($b); 1125937 5

ABCDE F

$c=11259375 decbin($c); $c=11259375 ($c >> 16); $c=11259375 $c=11259375 base_convert(($c>>16),10, 16); base_convert(($c >>16),10,2); 43981 abcd 171 AB

101010111100110111101 111 101010111100110111101 111

Elimina el carcter # de la cadena que contiene el color y determina sus valores hexadecimal, decimal y binario. Observa que el valor binario tiene 24 caracteres. Los 8 primeros son los dos dgitos hexadecimales del color rojo, los siguientes los del verde y los ltimos los del azul. Elimina 16 caracteres por la derecha en la cadena que contiene el valor binario. Transformamos el resultado a las distintas bases. Es la componente rojo del color Elimina 8 caracteres por la derecha en la cadena que contiene el valor binario. Transformamos el resultado a las distintas bases. Son las componente rojo yverde del color

10101011

$c=11259375 $h=($c >> 8); $c=11259375 $c=11259375 base_convert(($c >> 8),10,16); base_convert(($c >> 8),10,2);

1010101111001101 1010101111001101

$c=11259375 ($c >> 8 & 0xFF); $c=11259375 0xFF base_convert(($c>>8 & 0xFF),10,16); base_convert((0xFF),10,2);

205 CD 1111111111111111

$c=11259375

base_convert(($c>>8 & 0xFF),10,2);

1111111111001101

Por medio del operador &extraemos 8 caracteres por la derecha. La razn es que el valor binario de 0xFF (sera lo mismo poner el decimal 255) es 11111111 y operar & con esta cadena dara los 8 carcteres (observa que estos son 8 unos) de la derecha de la otra cadena operada. El resultado ser la componente verde del color. Estos son los valores iniciales. Los repetimos nicamente con el fin de facilitar la visualizacin de las cadenas binarias e ilustrar los procesos bit a bit El operador & compara cadenas de bits (por la derecha). Si ambos bits tienen valor 1 devuelve 1 en caso contrario devuelve cero. Por esa razn al comparar con 0xFF estamos comparando con unos y en consecuencia el resultado coincide con el valor de bit comparado. El resultado de esta comparacin es la componente azul del color.

$c=11259375 $c; $c=11259375 base_convert($c,10,16); $c=11259375 base_convert($c,10,2); $c=11259375 ($c & 0xFF); $c=11259375 0xFF base_convert(($c & 0xFF),10,16); base_convert((0xFF),10,2); base_convert(($c & 0xFF),10,2);

1125937 5 abcdef 101010111100110111101 111 239 EF 11111111

$c=11259375

11101111

El clculo utilizando los operadores bit a bit de la tabla anterior no es el nico posible. Es el ms rpido pero es equivalente a este otro realizado por medio de la aritmtica clsica. En un sistema de numeracin hexadecimal (por su condicin de ordenado y por ser su base igual a 16) siempre puede 5 4 3 2 1 0 convertirse el nmero en una forma polinmica del tipo: A*16 +B*16 +C*16 +D*16 +E*16 +F*16 , o tambin (utilizando nmeros de 4 2 0 4 dos cifras)AB*16 +CD*16 +EF*16 . Si dividimos el polinomio anterior entre 16 obtendremos AB como cociente entero 2 0 y CD*16 +EF*16 como resto. Si el resto anterior, CD*16 +EF*16 lo dividimos entre 16 obtendremos como cociente entero CD y como resto EF (16 =1). Los resultados de estas operaciones resultan ser las componentes de los tres colores. Por tanto, si partimos del valor $c=11259375 del ejemplo de la tabla anterior, tendramos que la componente roja (expresada en valor decimal) del color se obtendra mediante: (int)($c/pow(16,4))=171 sera el valor de la componente roja del color. El valor de (int)($c%pow(16,4)/pow(16,2))=205 nos dara la componente verde y, por ltimo, por medio de (($c%pow(16,4)) % pow(16,2))=239 sera el valor de la componente azul.
2 0 2 0

Filtros personalizados
Cualquiera de los efectos que puedan provocarse en una imagen es el fruto de modificar los valores de color de sus pixels. Este tipo de modificaciones individuales para un solo pixel pueden realizarse por medio de las funciones: $color=imagecolorAllocate($imagen,R,G,B) o $color=imagecolorallocatealpha($imagen,R,G,B,alfa) y imagesetpixel($imagen, $x, $y, $color)

Por medio de la primera de las funciones, ya comentada en pginas anteriores, se crea un ndice de color($color) para la imagen identificada por $imagen al que se asignan como valores de R, G y B valores enteros comprendidos entre 0 y 255. En el segundo de los supuestos, el parmetro alfa es un indicador de transparecia que puede tomar valores entre 0 (opaco) y 127 (transparente). El paso siguiente es aplicar la funcin imagesetpixel para asignar al pixel de la imagen$imagen cuyas coordenadas son x e y el color establecido en el ndice $color. Aqu tienes un ejemplo de como utilizar esas funciones para efectuar la transformacin Umbral que no es otra cosa que transformar a escala de grises y posteriormente modificar el color de los mismos asignando color rojo a aquellos cuyas componentes de color sean superiores a un valor umbral (por ejemplo 110) y color negro a aquellos que lo tengan inferior a ese valor.

<?php Header("Content-type: image/jpeg"); $im = imagecreatefromjpeg('./images/aviones4.jpg'); /* utilizamos imagesx e imagesy para calcular las dimensiones de la imagen actual. Tambin podramos haber utilizado los valores del array obtenido por medio de la funcion getimagesize que nos dara informacin de la imagen original. En este caso ambas son iguales */ $ancho=imagesx($im); $alto=imagesy($im); /* asignamos un valor entre 0 y 255 a la variable umbral dependiendo de este valor aumentarn o se reducirn las zonas blancas de la imagen */ $umbral=110; /* convierto a escala de grise grises */ imagefilter($im,IMG_FILTER_GRAYSCALE); /* creamos dos indices de color. Negro y rojo */ $color[0]=imagecolorAllocate($im,0,0,0); $color[1]=imagecolorAllocate($im,255,0,0); /* este doble bucle nos permite recorrer cada uno de los pixels de la imagen */ for ($i=0;$i<$ancho;$i++){ for ($j=0;$j<$alto;$j++){ /* leemos el color actual. Como se trata de grises las componentes R,G y B de cada uno de los pixels van a ser iguales, nos bastar por tanto conocer uno cualquiera. en este caso extraemos el valor correspondiente al azul */ $color_actual =imagecolorat($im,$i,$j) & 0xFF; /* si la componente gris es mayor que el umbral pinto en negro en caso contrario en blanco */ if($color_actual>$umbral){ imagesetPixel($im,$i,$j,$color[1]); }else{ imagesetPixel($im,$i,$j,$color[0]); } } } /* visualizamos la imagen */ imagejpeg($im); imagedestroy($im); ?>
Ver ejemplo Ver cdigo fuente

Creacin de una imagen CAPTCHA


CAPTCHA es el acrnimo de Completely Automated Public Turing test to tell Computers and Humans Apart que podra ser traducido como Prueba de Turing pblica y automtica para diferenciar a mquinas y humanos. Desde el punto de vista grfico

ha de ser una imagen el la que se visualizarn carcteres alfanumricos con elementos de distorsin y deformacin que impidan (o al menos dificulten) la lectura por dispositivos electrnicos OCR. Para dificultar ese proceso existen multitud de aplicaciones, clases PHP y recursos de toda ndoles. Nosotros vamos a intentar crear una imagen con poca nitidez, con caracteres aleatorios de diferentes tamaos, posiciones, tranparencias y ngulos de rotacin y posteriormente le aadiremos una deformacin vertical desplazando los pixeles en esta direccin por medio de funciones sinusoidales y, posteriormente haremos lo mismo en sentido horizontal. Veamos paso a paso el proceso.

Fondo con ruido aadido

Ver cdigo fuente

Insercin de caracteres aleatorios

Ver cdigo fuente

Deformacin vertical

Ver cdigo fuente

Deformacin horizontal

Ver cdigo fuente

Detectar bordes

Ver cdigo fuente

Filtros de convolucin Filtros de convolucin


Una imagen digital no es otra cosa que una especie de hoja de papel cuadriculado en el que cada una de las cuadrculas tiene asignado un color concreto especificado por medio de su cdigo de color tal como hemos visto en la pgina anterior. Cada uno de esos elementos que hemos llamado cuadrculas es un pixel. Una matriz de convolucin no es otra cosa que una matriz cuadrada formada por nueve cuadrculas (matriz de dimensin 3 x 3) que contiene valores numricos enteros. Aplicar un filtro de convolucin no es otra que superponer simblicamente la matriz de convolucin sobre la cuadrcula que conforma la imagen (El area sombreada de amarillo en la imagen sera delimitara sobre ella la zona de superposicin). El proceso aritmtico de aplicacin del filtro consistira en multiplicar el valor de cada cuadrcula de la matriz de convolucin por el situado debajo suyo en esa superposicin imaginaria. Los resultados de todos esos productos se sumaran obteniendo un valor que sustituira al valor del pixel centraldel area marcada (en rojo en la imagen). El valor anterior puede ser corregido por medio de un factor multiplicador del resultado y tambin por medio un parmetro de desplazamiento (offset) que permitira incrementar (o reducir, ya que admite valores negativos) en un valor entero el resultado anterior. En este esquema tienes el proceso de clculo del nuevo valor para el pixel central que es el marcado con fondo rojo.

La convolucin en PHP
Para aplicar este filtro en PHP es necesario empezar creando una matriz de convolucin. Dado que esa matriz ha de ser obligatoriamente de 3 x 3 la matriz de convolucin puede definirse de alguna de estas formas:

$matriz_de_convolucin = array(array(a11,a12,a13), array(a21,a22,a23), array(a31,a32,a33))

o tambin definiendo independientemente cada fila: $fila1 = array(a11,a12,a13) $fila2 = array(a21,a22,a23) $fila3 = array(a31,a32,a33)

y formando luego la matriz con las tres filas. Es decir: $matriz_de_convolucin = array($fila1, $fila2,$fila3)

Una vez disponemos de la matriz de convolucin podremos utilizar la funcin: imageconvolution ( $imagen , $matriz_de_convolucin, multiplicador, desplazamiento)

o, si preferimos definir la matriz de convolucin en la propia llamada a la funcin, escribiendo: imageconvolution ( $imagen , array(array(a11,a12,a13), array(a21,a22,a23), array(a31,a32,a33)), multiplicador, desplazamiento)

Dnde $imagen es el identificador de imagen, matriz_de_convolucion es el array ya comentado, multiplicador ser el factor multiplicador del resultado de la convolucin y desplazamiento un valor entero que se sumara a los resultados anteriores. El resultado sera la nueva imagen modificada despus de haber aplicado la matriz de convolucin a cada uno de los pixels que la conforman. Dado que los resultados no son facilmente predecibles hemos incluido simulador que te permitir ir modificando valores y observar los efectos producidos por esos cambios.

Imagen original

Imagen transformada

Cdigo fuente de la imagen

Si modificas las opciones de la parte inferior podrs visualizar aqu el cdigo fuente de los scripts que transforman la imagen original de acuerdo con los parmetros elegidos para cada opcin

Matriz de convolucin
0 0 0 0 1 0 0

Divisor:
0 0

1 0

Desplazamiento:

A modo de ejemplo, desde estos enlaces podrs visualizar los efectos indicados y a la vez las matrices de convolucin utilizadas. Sin convolucin Enfocar Desenfocar Repujado

Gestin de directorios Funciones con directorios


PHP dispone de funciones que permiten obtener informacin sobre los contenidos de los directorios del servidor. Algunas de estas funciones son las siguientes:

Pseudo-objeto dir
Mediante la expresin: $objeto = dir (path) dnde path es la ruta absoluta (../dir/subdir/subsubdir) o relativa (./subdir ) hasta el directorio del que vamos a obtener informacin, recogemos en el pseudo objeto $objeto la informacin sobre el directorio en cuestin de una forma un tanto peculiar ya que $objeto se comporta como objeto y, como tal objeto, posee las propiedades y mtodos que indicamos: $objeto->handle Devuelve una cadena con la descripcin del identificador del recurso. $objeto->path Devuelve la ruta del directorio especificado. $objeto->read() Realiza una lectura secuencial de los nombres y extensiones de los ficheros contenidos en el directorio especificado. $objeto->rewind() Posiciona el puntero en la posicin inicial. $objeto->close() Cierra el identificador de directorio. Este es un ejemplo de utilizacin de los mtodos de ste pseudo-objeto. Observa que las propiedades handle y path se invocan sin utilizar () mientras que tanto el mtodo read() como rewind() o close() s requieren esos parntesis.

<?php $directorio = dir("./images"); # en el caso de los objetos la manera de invocar # uno de sus mtodos y/o funciones requiere una sintaxis # especifica con la que vera a lo largo de este ejemplo: # es $objeto->metodo que equivale a la tradicional llamada # a una variable en la forma $variable. echo "Handle: ".$directorio->handle."<br>\n"; echo "Path: ".$directorio->path."<br>\n"; while($fichero=$directorio->read()) { echo $fichero."<br>\n"; } $directorio->rewind(); echo "nuevo listado del directorio despues de rebobinar<br>" ; while($fichero=$directorio->read()) { echo $fichero."<br>"; } $directorio->close(); ?>

ejemplo264.php

Otras funciones sobre directorios


Este nuevo grupo de funciones informativas requiere un sintaxis que recuerda la lectura de ficheros. Hay que comenzar abriendo el directorio y una vez se hayan realizado las consultas hay que cerrarlo segn se indica en las funciones siguientes. $directorio= opendir (path) Recoge en la variable $directorio un identificador que permitir utilizar las restantes funciones. $z= readdir ($directorio) Hace una lectura secuencial del directorio indicado por el identificador $directorio. A medida que efecta la lectura secuencial el puntero de lectura va desplazndose al fichero que sigue al ltimo ledo. rewinddir($directorio1) Rebobina haciendo que el puntero apunte al primer fichero del directorio. closedir($directorio1) Cierra el identificador del directorio.

<?php #abrimos el identificador de directorio $directorio = opendir("./images"); #leemos el primer fichero que ser "." (recuerda la estructura de los directorios de MSDOS) $fichero=readdir($directorio); echo $fichero,"<br>"; #leemos el fichero siguiente que ser ".." (recuerda la estructura de los directorios de MS-DOS) $fichero=readdir($directorio); echo $fichero,"<br>"; #leemos el fichero siguiente (el primer fichero "real") $fichero=readdir($directorio); echo $fichero,"<br>"; #rebobinamos, enviando el puntero al primer fichero rewinddir($directorio); echo "Lista de TODOS los ficheros usando un bucle while<br>"; #leemos todos los ficheros while($fichero=readdir($directorio)) { echo $fichero."<br>"; } closedir($directorio); ?>
ejemplo265.php

Proteccin de directorios Errores y redireccionamiento


Configuracin del servidor Apache
Para poder proteger de directorios mediante un fichero llamado .htaccess es necesario realizar algunas modificaciones en la configuracin de Apache. Abriremos nuestro fichero httpd.conf y buscaremos las lneas en las que aparece: AllowOverride None y reemplazaremos None por All. Guardaremos los cambios en httpd.conf y reiniciaremos el servidor. En caso de que estemos usando como sistema operativo Ubuntu haremos esa modificacin ejecutando desde consola: sudo gedit /etc/apache2/sites-enabled/000-default

El fichero .htaccess
Las misiones ms importantes que puede realizar este fichero son: redireccionar y restringir accesos. Veamos el primero de los casos. Los mensajes de error ms frecuentes al intentar acceder a pginas web y sus causas son los siguientes: Error 401 El subdirectorio est protegido por nmero IP o por password y el intento de acceder a l no ha tenido xito. Error 403 El acceso al documento solicitado est prohibido. Error 404 El documento solicitado no ha sido hallado. Error 500 Error del servidor. Usualmente este error se da cuando se ha intentado ejecutar de forma incorrecta un CGI, o bien debido a problemas en el servidor. Los errores de los tipos 403 y 404 suelen producirse en la mayora de las ocasiones por direcciones incorrectas y aparte de causar un psimo efecto suelen provocar el abandono de la visita. Un fichero .htaccess con este contenido: ErrorDocument 401 pagX ErrorDocument 403 pagY ErrorDocument 404 pagZ donde pagX, pagY y pagZ sean direcciones (completas) de las pginas a las que deseamos redireccionar el navegador, conseguira que esos errores llevaran al visitante a la pgina que nosotros deseramos. Intenta acceder a una direccin inexistente del tipo: http://localhost/noexisto.php y vers que aparece un mensaje de error advirtiendo que no existe ninguna pgina con ese nombre. Algo lgico, porque realmente no existe. Bastar con que abras tu editor no utilices el block de notas porque te dar muchsimos problemas en este caso escribas una lnea como esta ErrorDocument 404 http://www.rinconastur.net y guardes el documento en el raiz de tu servidor con el nombre .htaccess (aunque te parezca extrao, no lleva nada delante del punto). Reinicia el servidor, prueba nuevamente a acceder de nuevo a http://localhost/noexisto.php y observars que ahora no dice pgina no encontrada sino que se abre la pgina principal del este dominio. Edita de nuevo el fichero .htaccess y adele las siguientes lneas: ErrorDocument 401 http://www.rinconastur.net ErrorDocument 403 http://www.rinconastur.net

guarda los cambios, reinicia tu servidor y comprueba que cada vez que intentes acceder a una direccin inexistente te ocurre lo mismo que al pulsar aqu: http://rinconastur.net/noexisto.php. Como es lgico puedes redireccionar cada uno de los errores a una pgina distinta y, desde luego, no necesariamente a la ma. ;-)

Herencias
El archivo .htaccess provoca herencia. Eso significa que las especificaciones incluidas en un directorio sean restricciones o redirecciones son efectivas en todos los subdirectorios que contiene, incluso en el caso de que esos subdirectorios tengan su propio.htaccess y que en l se establezcan condiciones distintas a las anteriores. Al crear un fichero .htaccess las condiciones establecidas afectarn a todos sus subdirectorios. Por esa razn cuando pretendemos que desde subdirectorios distintos se redireccione a pginas distintas tendremos que incluir un .htaccess en cada uno de ellos y no poner ningn .htaccess en el directorio raz que los contenga.

Proteccin de directorios
Son muchas las posibilidades que ofrece .htaccess a la hora de restringir el acceso a un directorio determinado. Entre otras opciones, se puede denegar el acceso a todos los usuarios; denegar el acceso con excepciones, autorizar a todos (equivale a no restringir), autorizar con excepciones o requerir clave y contrasea. Lo que hemos denominado excepciones tambin permite una serie de alternativas tales como: una IP determinada, un rango de IP's, nombres de dominio, etctera. Slo comentaremos la forma de proteccin de directorios mediante claves de usuario y contrasea.

Restriccin de acceso a usuarios no autorizados


Este tipo de proteccin requiere crear un fichero de claves y contraseas y configurar de forma adecuada .htaccess Contraseas sin encriptar Para crear un fichero de claves y contraseas basta con abrir el block de notas y escribir la clave seguida de dos puntos (:) y a continuacin escribir la contrasea. Podemos poner tantas como deseemos sin ms limitaciones que escribir cada bloque clave:contraseaen una lnea distinta. Este puede ser un ejemplo:

pepe:Pepito pepa:Pepita
Podemos guardar este fichero en el sitio que deseemos sin que sea necesario que pertenezca al root del servidor que es la opcin ms aconsejable. Podemos ponerle cualquier nombre sin que importe que tenga extensin o no la tenga. Contraseas encriptadas Apache dispone de una utilidad que permite la creacin de ficheros de claves con contraseas encriptadas. Se trata de un programa llamado htpasswd.exe que est en el subdirectorio bin del servidor. Para crear un nuevo fichero el procedimiento sera el siguiente En la lnea de comandos: Inicio->Ejecutar

debemos escribir: path htpasswd -c nombre y path del fichero de claves usuario si se trata de un sistema operativo Linux Ubuntu habra que escribir en la consola htpasswd -c nombre y path del fichero de claves usuario

En nuestra configuracin y para crear un fichero con la palabra clave pepe escribiramos:
htpasswd -c /home/rinconas/seguridad/misclaves.txt pepe

y aparecera una ventana de MS-DOS en la que deberemos escribir la password para ese usuario.

Aadir usuarios a un fichero de contraseas encriptadas Porcederamos de la misma forma. Volveramos a ejecutar htpasswd con la nueva clave pero sin utilizar -c.

Cuidado! El modificador -c destruira el fichero anterior, si existiera y creara uno nuevo.


El proceso ahora sera:

htpasswd /home/rinconas/seguridad/misclaves.txt luis

Habramos creado as nuestro fichero con claves encriptadas. Si pretendiramos visualizarlo nos aparecera lo siguiente:

pepe:$apr1$EC4.....$7Z3.p2tv2QpzrZbo4bI2j0 luis:$apr1$SU4.....$iU8a.YTo.ZvYyRggDAvTC. Cuidado! Bajo Linux, antes de aadir el usuario luis tendramos que asegurarnos de que el fichero misclaves.txt tenga permisos para poder efectuar modificaciones en su contenido.

Configuracin de .htaccess
Para el caso especfico de nuestro servidor Apache, el fichero .htaccess ha de contener: AuthType Basic No permite modificacin e indica el tipo de autentificacin requerida. AuthName "nuestro texto " El texto que escribamos aqu aparecer como mensaje en la ventana en la que nos pedir la clave AuthUserFile "path" Entre esas comillas debes escribir el nombre del fichero de contraseas especificando su path completo. require valid-user Este texto indica que para acceder se requiere un usuario vlido. Con nuestra configuracin de Apache no es necesario especificar en .htaccess la forma de encriptacin de contraseas. El propio servidor interpreta el contenido del fichero y aplica u omite los criterios de encriptacin. A riesgo de parecerte pesados tenemos que volver a insistir que no todos los hosting tienen habilitada esta opcin, pero adems hemos de hacer mencin a otro detalle muy importante. La configuracin que hemos comentado no es vlida para todos los servidores. Segn como est configurado el servidor, la versin del software que utilice, etctera no sera extrao que se necesitara esta otra sintaxis: AuthType Basic, AuthName "Texto", AuthTextUserFile fichero, required valid-user, AuthTextCrypt On/Off u otras similares que pueden inducirnos al error. Lo mejor, en caso de servidores ajenos, es consultar al administrador del sistema sobre estos aspectos y recabarle detalles sobre la sintaxis especfica de su configuracin.

Un ejemplo de .htaccess
Supongamos que tenemos un directorio llamado protegido en cualquier parte del servidor (por ejemplo dentro de htdocs). La forma de protegerlo sera crear un fichero con nombre .htaccess con un contenido como este:

AuthType Basic AuthName "Pruebas de autentificacin" AuthUserFile "c:/Apache/seguridad/misclaves.txt" require valid-user


y guardarlo en el directorio que hayas especificado en lugar de lo escrito en rojo en el recuadro anterior. Al acceder al directorioprotegido aparecer una ventana como esta:

y si al cabo de tres intentos no escribimos la clave y contrasea adecuadas se producir un Error 401. Una vez que tengamos modificada la configuracin del servidor Apache estaremos en condiciones de poder proteger directorios restringir o limitar el acceso a ellos y tambin podremos redirigir peticiones a pginas predeterminadas en casos concretos. Este control ha de realizarse mediante ficheros que tienen por nombre .htaccess (el primer caracter es el punto), que no pueden llevar ningn tipo de extensin y que pueden ser incluidos en cualquier directorio o subdirectorio del espacio del servidor.

Cuidado! Existen otras opciones de proteccin de acceso a directorios. Algunas guardan la lista de usuarios autorizados en una base de datos y otras requieren que el usuario disponga de un certificado digital. En el epgrafe Servidores seguros tienes informacin al respecto.

Las cookies Las cookies


De igual modo que ocurra con la funcin mail, no todos los hosting tienen habilitada la opcin de envo de cookies. Como sabes, lascookies son pequeos ficheros que se escriben en el ordenador del cliente. Si utilizas Internet Explorer podrs ver que se almacenan como ficheros de texto en un directorio llamado Archivos temporales de Internet y que su nombre es de este tipo: cookie:xxx@nombre[z].txt donde xxx suele ser el nombre que figura en el registro de Windows como nombre del equipo (el que se pone al instalar Windows); nombre suele ser el nombre del directorio de servidor desde el que se envi la cookie y el nmero z suele ser el ordinal del nmeros de accesos a la pgina que enva la cookie. Firefox trata las cookies de forma distinta. Las almacena en un nico fichero llamado cookies.sqlite que suele encontrarse en:C:\Documents and Settings\Usuario\Datos de programa\Mozilla\Firefox\Profiles\xxxx.default. En cuanto a Google Chrome tambin utiliza un nico fichero llamado cookies que suele estar en un directorio como este: C:\Documents and Settings\Usuario\Configuracin local\Datos de programa\Google\Chrome\User Data\Default En el caso de usar Ubuntu como sistema operativo el fichero cookies.sqlite de Firefox puedes encontrarlo en un directorio cuya ruta ser similar a esta: /home/(nombre_de_usuario)/.mozilla/firefox/xxxx.default

Enviar y leer cookies


La instruccin para el envo de cookies debe insertarse al principio de la pgina y antes de cualquier etiqueta HTML o lnea en blanco. Esto es muy importante, no lo olvides. La sintaxis es la siguiente: setcookie(nombre, valor, expira)

donde nombre es una cadena que contiene el nombre de la variable que recoge el valor de la cookie, valor es el valor, numrico o cadena, que se asignar a la variable anterior y expira indica la fecha de caducidad de la cookie que suele expresarse usando el valor devuelto por la funcin time() (hora actual) ms un nmero que representa los segundos que han de transcurrir desde ahora hasta que lacookie expire. Los valores contenidos en las cookies pueden ser ledos por el servidor a partir de variables predefinidas $_COOKIE que, como todas las de este tipo, es un array asociativo. El ndice de este array ser el nombre asignado a la cookie. Veamos este ejemplo:

<?php /* setcookie escribe el contenido de la cookie en el ordenador del cliente */ setcookie("cookie1","Soy la cookie1",time()+3600); # escribe el valor leido en la cookie @print "Esta es la <i>galletita</i>: ".$_COOKIE['cookie1']; ?>
ejemplo266.php

Al ejecutar por primera vez este script (o al hacerlo despus de limpiar o eliminar historial de navegacin en el cliente) solo leeremos el texto Esta es la galletita : sin nada detrs. La explicacin es la siguiente: las instrucciones PHP se ejecutan en el servidor antes de enviar la pgina al cliente. Eso significa que, al ejecutar por primera vez, se inserta la orden de escritura y se comprueba el valor de la variable, que aun no ha sido creada y por ello aparece en blanco. Ser en la actualizacin ya se habra producido un envo al navegador y ya se habra escrito la cookie cuando si se leer el valor anterior Dado el carcter superglobal de $_COOKIE tambin se le puede aplicar la funcin extract tal como hemos comentado en al tratar el tema de los formularios. En este ejemplo podemos ver esa opcin

<?php extract($_COOKIE); @print "Esta es la galletita leida desde extract: ".$cookie1; ?>
ejemplo267.php

Como es lgico los valores de las cookies pueden asignarse tambin por medio de variables tal como puedes comprobar en estos ejemplos:

<?php $variable="Ahora me han incluido desde una variable"; setcookie("cookie2",$variable,time()+3600); @print "Esta es la nueva cookie: ".$_COOKIE['cookie2']; ?>
ejemplo268.php

<?php print "Estoy leyendo la cookie2: ".$_COOKIE['cookie2']; extract($_COOKIE); print "<br>Sigo leyendo lo mismo a travs del resultado de extract: ".$cookie2; ?>
ejemplo269.php

Una cookie definida como array

Una cookie puede contener varios valores agrupados en un array. Para ello basta con incluir en setcookie el nombre y el ndice de un array utilizando un setcookie por cada uno de los elementos del array tal como puedes ver en el ejemplo. Para leer las cookies enviadas de esta forma bastar con leer el array devuelto.

Cuidado! Fjate en la sintaxis de setcookie del ejemplo. Los nombres de los ndices del array no se escriben entre comillas. Observa tambin que al leer los datos de la cookie hemos de tratarla como un array bidimensional. El primer ndice el nombre de la cookie (en nombre del array que contiene la informacin) y el segundo ser el nombre concreto de cada uno de los ndices tal como han sido creados. <?php $valores=Array("Verde","Verano","Rolls-Royce","Millonario"); # a diferencia de lo que ocurre al definir elementos de array asociativos # en este caso los indices asociativos (color, estacin, etc.) no van # entre comillas setcookie("cookie3[color]",$valores[0],time()+3600); setcookie("cookie3[estacion]",$valores[1],time()+3600); setcookie("cookie3[coche]",$valores[2],time()+3600); setcookie("cookie3[finanzas]",$valores[3],time()+3600); # la variable superglobal $_COOKIE['cookie3'] contiene un array, por ello # la lectura de sus valores debe hacers considerando que se trata de un # array bidimensional @print "<br>El color viene en $_COOKIE['cookie3']['color'] y es: ".$_COOKIE['cookie3']['color']; @print "<br>La estacin $_COOKIE['cookie3']['estacion'] y es: ".$_COOKIE['cookie3']['estacion']; @print "<br>La finanzas $_COOKIE['cookie3']['finanzas'] estn: ".$_COOKIE['cookie3']['finanzas']; @print "<br>El coche es $_COOKIE['cookie3']['coche'] y es: ".$_COOKIE['cookie3']['coche']; print "<br> tambin podemos leer la cookie mediante un bucle como este:<br>"; if (isset($_COOKIE['cookie3']) ) { while( list( $indice, $valor) = each($_COOKIE['cookie3']) ) { echo "$indice == $valor\n"; } } ?>
ejemplo270.php

Un contador de visitas como aplicacin prctica


<?php @$numero=$_COOKIE['visitante']; $numero+=1; setcookie("visitante",$numero,time()+86400); if($numero==1){print "Es la $numero vez que visitas esta pgina";} if($numero>1){print "Es la $numero vez que visitas esta pgina";} ?>
ejemplo271.php

Cambio del color de fondo

<?php @$numero=$_COOKIE['color']; $numero+=1; setcookie("color",$numero,time()+86400); extract($_COOKIE); $colores=array('red','blue','yellow','green','black'); /* el fondo de la pgina tendr uno de estos cinco colores de fondo dependiendo del resto de la division entre 5 del nmero de visitas efectuadas hasta el momento */ @print "<body bgcolor='".$colores[$color%5]."'></body>"; ?>
ejemplo272.php

Sesiones Qu son las sesiones?


Suponemos que habrs estado alguna vez en un hotel y que recuerdas que al inscribirnos como huspedes nos facilitan una tarjetita identificativa que tericamente habramos de presentar a la hora de solicitar cualquier servicio del hotel (cafetera, restaurante, etc.). Al registrarnos en ese hotel estaremos iniciando una sesin (estancia) y al recibir la tarjeta identificativa se nos estar facilitando un identificador de sesin, que tiene validez temporal, ya que expirar en la fecha de salida indicada en ella y que recoge una serie de datos (nuestros datos personales, nuestro perodo de estancia, el precio y los servicios contratados, etctera). Imaginemos ahora que vamos al restaurante. Pueden ocurrir dos cosas: que decidamos efectuar el pago directamente, o que pidamos que el importe de la factura se incluya en nuestra cuenta. En el segundo de los casos, se reiniciar la sesin y se registrar una nueva variable de sesin el importe del servicio al firmar la nota de cargo del mismo. El responsable del restaurante deber guardar en algn sitio (probablemente en la oficina de recepcin) esa nota de cargo una variable de sesin de forma temporal ya que una vez abonado su importe o en el momento que abandonemos el hotel expirar la sesin y dejar de tener utilidad. Se requiere de forma imprescindible un directorio temporal en el que almacenar las variables de sesin. En PHP la sesiones funcionan de forma muy similar y de esa similitud surge la necesidad de habilitar un directorio temporal antes de utilizar sesiones. Si visualizamos el fichero info.php y buscamos la directiva session.save_path veremos que, en el caso de Windows tiene el valor C:/ServidoresLocales/tmp como consecuencia de la creacin del directorio tmp y de la modificacin que hicimos en la lnea 1471 dephp.ini cuando detallbamos el proceso de configuracin de php (puedes verlo aqu). En el caso de la instalacin sobre Ubuntu esa configuracin se hace de forma automtica. Al observar info.php podras ver que:session.save_path="/var/lib/php5" La posibilidad de propagacin de las sesiones y con ellas la informacin guardada en las variables de sesin ($_SESSION) son instrumentos de enorme utilidad en la gestin de de pginas web.

Funciones de sesin
Para la gestin de sesiones se utilizan estas funciones: session_start() Crea una sesin o contina con la actual. En el segundo caso el identificador de sesin debe ser tranferido por medio de una variable GET o a travs de una cookie. session_name()

Recoge el nombre de la sesin. Si no se asigna uno de forma explcita utiliza como nombre de sesin el contenido de la directivasession.name del fichero php.ini. Por defecto ese nombre suele ser PHPSESSID, pero no est de ms comprobarlo mirando el valor actual de la directiva session.name en info.php. session_name('nombre') Esta variante de la funcin anterior permite asignar un nuevo nombre a la sesin actual. Debemos tener en cuenta que si cambiamos de pgina y queremos mantener el mismo identificador (conservar la sesin anterior) esta funcin debe ser incluida con el mismo nombreen la nueva pgina y, adems, ha de ser insertada antes de que la funcin session_start() se invocada para iniciar la sesin. session_cache_limiter() El limitador de cach controla las cabeceras HTTP enviadas al cliente. Estas cabeceras determinan las reglas mediante las que se habilita la opcin de que los contenidos de las pginas puedan ser guardados en la cach local del cliente o se impida tal almacenamiento. En este ltimo modo no cach cada peticin de pgina requerira una nueva llamada al servidor, lo cual tiene como todo en la vida ventajas e inconvenientes. Entre las ventajas est la garanta de que en cada acceso estamos viendo la versin actualizada de la pgina, cosa que podra no ocurrir de otro modo. El inconveniente es que requiere una nueva peticin que puede significar un tiempo de espera, mientras el servidor produce la respuesta. Esta opcin viene configurada por defecto en las directivas de configuracin del php.inicomo nocache. Para evitar sea cual fuera la configuracin de php.ini el almacenamiento de las pginas en la cach del cliente hemos de utilizar: session_cache_limiter ('nocache,private') Igual que ocurra con session_name, si utilizamos est funcin debemos escribirla antes que session_name y tambin igual que en aquel caso deberemos repetirla en cada uno de los documentos. Por tanto, el orden de escritura de estas instrucciones sera el siguiente: <?php session_cache_limiter(); session_name('nombre'); session_start(); ..... ?> Es muy importante mantener ese orden y que este bloque de instrucciones sea el primer elemento de la pgina antes de cualquier otra etiqueta y que no haya lneas en blanco ni antes de la etiqueta <?php ni entre ella y las llamadas a estas funciones.

Propagacin de las sesiones


La verdadera utilidad de las sesiones estriba en su propagacin, es decir, la posibilidad que tanto el identificador de sesin como losvalores de las variables de sesin luego hablaremos de estas variables puedan ir pasando de una pgina a otra sin necesidad de recurrir al uso de formularios. Para entendernos, se trata de dar validez y utilizar la misma tarjeta para movernos por las diferentes secciones delhotel que hemos utilizado como ejemplo. La forma habitual de propagar las sesiones es a travs de cookies, pero como quiera que el usuario tiene la posibilidad de desactivar la opcin (no aceptar cookies) PHP dispone una opcin alternativa que permite la propagacin a travs de la URL an en el caso de que lascookies estn desactivadas.

Caso de que el cliente tenga activada la opcin aceptar cookies


Si queremos que las sesiones se propaguen nicamente en el caso de que est activada la opcin aceptar cookies en el navegador bastar con hacer la llamada a la nueva pgina siguiendo el mtodo tradicional, es decir: <A href="pagxx.php"> y que esa nueva pgina contenga sin que lo preceda ninguna lnea en blanco el script siguiente:

<? session_cache_limiter(); session_name('nombre'); session_start(); ..... ?> donde no es imprescindible incluir session_cache_limiter pero cuando se incluye ha de ir como primera lnea del script. Consession_name ocurre algo similar. Si la sesin fue iniciada con un nombre distinto al que le asigna por defecto PHP, debemos escribirsession_name('nombre'), y adems, nombre debe tener el mismo valor que en la pgina precedente. Si no se asigna ningn nombre tomar el valor PHPSESSID nombre por defecto en todas las pginas y no ser necesaria la instruccin session_name.

Caso de cookies deshabilitadas


Para garantizar la propagacin de las sesiones an cuando el navegador est configurado para no aceptar cookies tendremos quepasar el identificador de sesin junto con las llamadas a las pginas siguientes. Para ello se requiere la siguiente sintaxis: <A href="pagxx.php?<?php print echo session_name()."=".session_id():?>" Con esta sintaxis, despus de escribir el ? (recordemos que es la forma de indicar que aadimos variables y valores para que sean transferidos junto con la peticin de la pgina) estaremos pidiendo a PHP que escriba como nombre de variable el nombre de la sesin y como valor de esa variable, despus de insertar el signo igual, el identificador de sesin. Es evidente que la utilizacin de esta opcin nos permite asegurar que las sesiones y sus variables podrn ser usadas sin riesgos de que una configuracin inadecuada por parte del cliente produzca resultados imprevisibles.

Algunos ejemplos
Aqu tenemos un ejemplo de como iniciar una sesin y tambin podremos comprobar como se propaga al llamar a la misma pgina si est activada la opcin aceptar cookies. Si ejecutamos reiteradamente el script pulsando en volver a llamar esta pgina podremos ver que no se modifica el valor del identificador de sesin. Si bloqueamos las cookies (en este enlace est descrito el procedimiento para hacerlo) podremos comprobar que ahora la sesin no se propaga y que cada vez que volvemos a llamar a la pgina nos aparece un nuevo valor en el identificador de sesin, es decir, se crea una nueva sesin.

<?php session_start(); #pedimos que escriba el identificador nico y el nombre de la sesin echo session_id(),"<br>"; echo session_name(),"<br>"; ?> <A Href="ejemplo273.php">Volver a llamar estallamar esta pgina</A>
ejemplo273.php

Ahora haremos una modificacin importante en el script. Al incluir en la llamada a la pgina el nombre y el identificador de sesinestamos transfiriendo mediante el mtodo GET el valor de esa variable. De esta forma, la propagacin de la sesin estar asegurada sea cual fuere la configuracin del navegador del cliente. Podemos comprobar activando/desactivando cookies que en las sucesivas llamadas a la pgina se mantiene el identificador de sesin.

<?php session_start(); #pedimos que escriba el identificador nico y el nombre de la sesin echo session_id(),"<br>"; echo session_name(),"<br>";

?> <A Href="ejemplo275.php?<?php echo session_name()."=".session_id();?>">Volver a pgina</a>


ejemplo275.php

esta

Sesiones con nombre propio En los ejemplos siguientes se crean y propagan sesiones con nombre propio sin que ello altere las condiciones de respuesta con las opciones aceptar /no aceptar cookies. Tambin hemos incluido session_cache_limiter con las restricciones de nocache con lo cual el navegador no guardar las pginas de ejemplo en la cach. Si cambiramos los parmetros (nocache, private por public) podramos comprobar si se almacena en la cach del navegador la pgina web devuelta por el servidor.

<?php session_cache_limiter('nocache,private'); session_name('leocadia'); session_start(); #pedimos que escriba el identificador nico echo session_id(),"<br>"; echo session_name(),"<br>"; ?> <A Href="ejemplo276.php">Volver a llamar esta pgina</A>
ejemplo276.php

<?php session_cache_limiter('nocache,private'); session_name('leocadia'); session_start(); #pedimos que escriba el identificador nico echo session_id(),"<br>"; echo session_name(),"<br>"; ?> <A Href="ejemplo278.php?<?php echo session_name()."=".session_id()?>">Volver a esta pgina</A>
ejemplo278.php

Las cookies de sesin y sus parmetros


Para el caso de que el navegador del cliente tenga activada la opcin de aceptar cookies PHP dispone de una funcin que permiteleer los parmetros de esa cookie. Es la siguiente: session_get_cookie_params() que devuelve un array asociativo con los siguientes ndices: lifetime: Indica el tiempo de duracin de la duracin de la cookie path: Indica la ruta -en el ordenador del cliente- en la que se almacenan los datos de la sesin domain :Indica el dominio de procedencia de la cookie. secure :Indica si la cookie solo puede ser enviada a travs de conexiones seguras (1) o si no considera esa posibilidad (0). Los valores por defecto para estos parmetros se pueden establecer en la configuracin del fichero php.ini. Si visualizamos info.phppodremos ver en las directivas session.cookie_xxx nuestros valor por defecto y observaremos que session.cookie_lifetime tiene valor 0, razn por la cual si con la opcin aceptar cookies activada ejecutamos cualquiera de los script anteriores y miramos el directorio Temporal Internet Files, no encontraremos ninguna de estas cookies, dado que su plazo de expiracin es cero.

<?php session_name('mi_sesion'); session_start();

echo session_id(),"<br>"; echo session_name(),"<br>"; # recogemos en la variable $a el array con los datos de la sesin $a=session_get_cookie_params(); foreach($a as $c=>$v){ echo $c,"--->",$v,"<br>"; } ?> <A Href="ejemplo279.php">Volver a llamar esta pgina</a>
ejemplo279.php

<?php session_name('mi_sesion'); session_start(); echo session_id(),"<br>"; echo session_name(),"<br>"; # recogemos en la variable $a el array con los datos de la sesin $a=session_get_cookie_params(); foreach($a as $c=>$v){ echo $c,"--->",$v,"<br>"; } ?> <A Href="ejemplo281.php?<?php echo session_name()."=".session_id()?>">Volver a esta pgina</A>
ejemplo281.php

Las configuraciones de session.cookie pueden cambiarse sin necesidad de modificar el fichero php.ini. Para ello disponemos de la funcin: session_set_cookie_params(duracin ,'path','dominio',segura) que permite configurar esos parmetros de forma temporal unicamente para la pgina en la que est insertado y que como en los casos anteriores puede configurarse slo para el caso de que el navegador acepte cookies como para las situaciones en la que esa opcin est deshabilitada. En estos ejemplos escribir siempre que est configurada la opcin aceptar cookies en el navegador del cliente una cookie que tendr una caducidad de DIEZ minutos (el valor 10 de session_set_cookie_params). Esa cookie se guardar en el mismo directorio (/) donde se guardan las pginas web visitadas (el famoso C:\WINDOWS\Temporary Internet Files, en la configuracin por defecto de IE), pero..., eso solo ocurrir si tal como ves en el ejemplo pones en el parmetro dominio elnombre real del dominio donde est alojada la web. Si el nombre de dominio no coincide con que alberga la pgina razonable criterio de seguridad no se guardar la cookie.

<?php session_set_cookie_params (10,"/","localhost", 0); session_name('mi_sesion'); session_start(); echo session_id(),"<br>"; echo session_name(),"<br>"; $a=session_get_cookie_params(); foreach($a as $c=>$v){ echo $c,"--->",$v,"<br>"; } ?> <A Href="ejemplo282.php">Volver a llamar esta pgina</A>
ejemplo282.php

<?php session_set_cookie_params (10,"/","localhost", 0);

session_name('mi_sesion'); session_start(); echo session_id(),"<br>"; echo session_name(),"<br>"; $a=session_get_cookie_params(); foreach($a as $c=>$v){ echo $c,"--->",$v,"<br>"; } ?> <A Href="ejemplo284.php?<?php echo session_name()."=".session_id()?>">Volver a esta pgina</A>
ejemplo284.php

Manejo de variables de sesin


Las funciones ms importantes para el manejo de variables de sesin son las siguientes: $_SESSION['variable']=valor es una de las formas de definir una variable de sesin. El ndice variable debe contener entre comillas el nombre que pretendamos asignarle a esa variable de sesin y valor sera el valor asignado a esa variable. Si ya existiera le reasignara el nuevo valor. unset($_SESSION); La funcin unset destruye las variables contenidas en el parntesis. En este caso, al contener el array $_SESSION destruira todas las variables contenidas en l. unset($_SESSION['variable']); Es similar a la anterior. En este caso solo sera destruida el elemento del array cuyo ndice sea var. isset($_SESSION['variable']); La funcin isset no es especfica del tratamiento de sesiones devuelve un valor booleano (UNO NUL) segn que exista o no exista la variable contenida en el parntesis. De hecho, se comporta con las variables de sesin de forma idntica a como lo hara con cualquier otro tipo de variable.

<?php # iniciamos la sesin session_start(); # visualizamos el identificador de sesin print "Este es el identificador de sesion: ".session_id()."<br>"; # registramos una variable de sesin asignandole un nombre $_SESSION['variable1']=""; #asignamos un valor a esa variable de sesin $_SESSION['variable1']="Filiberto Gmez"; /* registramos una nueva variable de sesin asignandole directamente un valor */ $_SESSION['variable2']="Otro filiberto, este Prez"; #comprobamos la existencia de la variables de sesin @print "Mi_variable1 esta registrada: ".isset($_SESSION['variable1'])."<br>"; #leemos el contenido de esa variable @print "Su valor es: ".$_SESSION['variable1']."<br>"; #comprobamos la existencia de la otra variable y la visualizamos @print "Mi variable2 esta registrada :".isset($_SESSION['variable2'])."<br>"; print $_SESSION['variable2']."<br>"; #destruimos la variable1 unset($_SESSION['variable1']); @print "La variable1 ha sido destruida:".isset($_SESSION['variable1'])."<br>";

@print $_SESSION['variable1']."<br>"; #destruimos todas las variables restantes unset($_SESSION); #comprobamos que han sido destruidas @print "La variable1 ya estaba vacia: ".isset($_SESSION['variable1'])."<br>"; @print $_SESSION['variable1']."<br>"; @print "Tambin ha sido destruida la variable2: ".$_SESSION['variable2']."<br>"; @print $_SESSION['variable2']."<br>"; ?>
ejemplo285.php

Propagacin de sesiones
Los tres scripts siguientes son un ejemplo del uso de sesiones para la propagacin de sesiones. Funcionan bajo cualquier forma de register_globals y tambin en el caso en que las cookies estuvieran desactivadas en el navegador del cliente

<?php /* recuerda que entre <?php y la primera lnea no puede haber lneas en blanco ni tampoco puede haberla encima de <? aunque como en este caso, si admite lneas de comentario pero no lneas en blanco */ # deactivamos la opcion de que las pginas puedan guardarse # en la cache del navegador del cliente session_cache_limiter('nocache,private'); # le asignamos un nombre a la sesin # aunque lo habitual sera dejar el nombre por defecto # que le asigna la configuracin de php.ini session_name('pruebas'); # iniciamos la sesion session_start(); # creamos variables de sesion y les asignamos valores $_SESSION['valor1']=25; $_SESSION['valor2']="Ambrosio de Morales"; $_SESSION['variable3']="Una prueba ms"; /* cerramos el script e insertamos un enlace a otra pgina y propagamos la sesin incluyendo en la llamada el nombre de la session y su identificador En esta pgina no se visualizara nada. Solo el enlace */ ?> <A Href="ejemplo287.php?<?php echo session_name()."=".session_id()?>">Propagar la sesion</A>
ejemplo286.php

<?php /* pese a que la sesion viene de la pgina anterior tenemos que poner nuevamente session_cache_limiter ya que esta instruccion no se conserva solo es vlida para la pgina en la que esta definida Tambin tenemos que poner en session_name el mismo nombre de la pgina anterior, de no hacerlo PHP entendera que se trata de iniciar una sesion distinta Por ultimo tambin debemos iniciar la sesin es obligatorio iniciarla */ session_cache_limiter('nocache,private'); session_name('pruebas');

session_start(); /* comprobaremos que la sesion se ha propagados visualizando el array asociativo $_SESSION que contiene todas la variables de Sesion */ foreach($_SESSION as $indice=>$valor){ print("Variable: ".$indice." Valor: ".$valor."<br>"); } # modificamos los valores de las variables de sesion # de igual forma que si fueran variables de cualquier otro tipo $_SESSION['valor1']+=87; $_SESSION['valor2'] .=" bonito nombre"; # destruimos la tercera variable unset($_SESSION['variable3']); # propagamos la sesion a la pgina siguiente # con identico proceso al del script anterior ?> <A Href="ejemplo288.php?<?php echo session_name()."=".session_id()?>">Propagar la sesion</A> <?php # identicos comentarios a los anteriores session_cache_limiter('nocache,private'); session_name('pruebas'); session_start(); # este bucle nos confirmar que se han propagado # los nuevos valores y que la tercera variable ha sido destruida foreach($_SESSION as $indice=>$valor){ print("Variable: ".$indice." Valor: ".$valor."<br>"); } ?>

Clases y objetos (I) Clases y objetos


Aunque PHP 5 no es un lenguaje orientado a objetos, s tiene recursos que permiten definir clases y construir objetos. El modelo de objetos de PHP 5 ha sido reescrito en su prctica totalidad y presenta sustanciales diferencias respecto a las versiones anteriores. El uso declases y objetos (POO Programacin Orientada a Objetos) no aade ninguna funcionalidad nueva a las posibilidades de PHP. Su verdadera utilidad es la de hacer la programacin de otra manera, con un cdigo ms legible y reutilizable.

Las clases
Una clase no es otra cosa que una especie de plantilla dentro de la cual se pueden definir una serie de variables llamadaspropiedades que pueden contener valores predefinidos y un conjunto de funciones denominadas mtodos que pueden ser invocadasdesde cualquier parte del documento por un objeto o instancia de esa clase. La sintaxis que permite definir una clase es siguiente: class nombre { .... ... definicin de variables y/o propiedades.... .... .. constructor (opcional)...

.... .. destructor (opcional)... .... .. definicin de mtodos o funciones ... .... }

Vayamos por partes. La palabra reservada class es obligatoria y ha de ir seguida de un nombre mediante el que ser identificada la clase. La definicin de la clase comienza con un llave de apertura ({) y acaba con una llave de cierre (}). Entre ambas llaves podemos incluir sus variables o propiedades y tambin sus mtodos o funciones. A las variables o propiedades pueden serles asignados valores, aunque no es imprescindible hacerlo. Los mtodos o funcionestienen una sintaxis muy similar a la utilizada en la programacin estructurada. Entre los mtodos o funciones susceptibles de ser incluidos en una clase existen dos bastante especiales. Son los llamadosconstructor y destructor. Ninguno de ellos tiene carcter obligatorio. Su peculiaridad estriba en que se ejecutan de forma automtica en determinadas circunstancias. Hablaremos de ellas un poco ms adelante.

Definicin de las propiedades


Para definir una variable o propiedad en una clase es obligatorio anteponer a su nombre una de estas tres palabras reservadas:public, private o protected. Por compabilidad con versiones anteriores de PHP si se usa la palabra var ser interpretada como un alias depublic. El nombre de la variable utiliza la sintaxis habitual de PHP y en el caso de que tratemos de asignarle un valor, bastar con poner detrs del nombre el signo = seguido de ese valor que en el caso de ser una cadena tienen que ir entre comillas. A modo de ejemplo podemos decir que public $pepe="Jose" es una sintaxis vlida, pero que $pepe="Jose" no lo es dado que le falta la palabra reservada (opcin de visibilidad) que obligatoriamente debe llevar delante de su nombre y que de no ser incluida provocara un error. Lo que se conoce como encapsulamiento es uno de los pilares bsicos de la Programacin Orientada a Objetos. Permite establecer las condiciones y/o restricciones de visibilidad de los diferentes elementos (propiedades y mtodos) de una clase. Cuando al definir una variable o propiedad anteponemos a su nombre la palabra public estamos estableciendo ese carcter pblico de visibilidad que significa que sus valores pueden ser vistos e incluso modificados desde cualquier parte del script en que sean invocadas. Por el contrario, si establecemos la visibilidad como private (privada) estamos encapsulando la informacin de forma que sus valores slo son accesibles a travs de mtodos o propiedades incluidos en la propia clase. La tercera de las posibilidades, protected (protegida), flexibiliza un poco la condicin private al permitir que el mtodo o propiedad sea ser visible desde la propia clase y desde sus clases extendidas (las trataremos un poco ms adelante cuando nos refiramos a la herencia).

Funciones o mtodos de clase


Los mtodos o funciones definidas en las clases que tienen una sintaxis casi idntica al resto de las funciones PHP function nombre( ){ ... instrucciones.... .... }

Las diferencias ms sustanciales respecto a las funciones de la programacin estructurada son: Los mtodos siguen los mismos criterios de encapsulamiento que hemos comentado al hablar de las propiedades. Se establecen anteponiendo a la palabra function una de las tres palabras public, private o protected aunque en este caso si se omite no se genera error sino que el mtodo es considerado como public. Siempre que desde un mtodo se invoque una variable o propiedad definida en la misma clase ha de hacerse mediante la sintaxis: $this ->propiedad. Los mtodos de la propia clase se invocan de esta forma: $this->nombre_de_la_funcion(). Como es lgico dentro del parntesis pueden incluirse los parmetros o argumentos que sean necesarios.

Prestemos mucha atencin. El $ va siempre delante de la palabra this y solo se escribe una vez y en esa posicin. El nombre de la variable (que va siempre despus de -> no lleva el $. Este es un ejemplo de una clase muy sencilla. Como ves el nombre de la clase es MiClase. Como es lgico, si tratas de ejecutar el ejemplo no obtendrs ningn resultado. Ser necesario que un objeto utilice esta clase.

<?php class MiClase{ public $factor1=7; // esta es pblica private $factor2=8; // variable privada protected $factor3=3; // variable protegida function calcula($a=3,$b=5){ // al no indicar visibilidad ser public return $this->factor1-$b^2+$this->factor2*$a-$this->factor3; } } ?>
ejemplo299.php

Los objetos
Las clases son solo plantillas y sus mtodos no sern ejecutados en tanto no exista un objeto que requiera su aplicacin. Dicho en forma coloquial, una clase es como una sartn. En tanto no tengamos algo que freir carece de utilidad alguna. Su razn de ser son los objetos susceptibles de se cocinados por ella. Lo mismo ocurre con las clases cuya autntica razn de ser es servir para la creacin y manejo de sus objetos.

Creacin y destruccin de objetos


Para crear un nuevo objeto (instancia de la clase) que utilice una clase determinada debemos usar la siguiente sintaxis: $objeto = new clase

donde objeto es una palabra cualquiera con la que identificar el objeto (como si se tratara de una variable), new es una palabra reservada obligatoria y clase es el nombre de una clase que puede estar escrita en el mismo documento o en un fichero externo. Si la clase est escrita en un documento distinto del que contiene el script que crea el objeto habremos de utilizar include o require para incluirla. Cuidado! Fjate que por el momento no hemos puesto los () requeridos para invocar las funcionesdetrs del nombre de la clase.

Cuando se trata de eliminar un objeto (liberar el rea de memoria que contiene toda la informacin relativa a este) podemos utilizar la siguiente sintaxis: $objeto = null o unset(objeto ) si bien es cierto que se destruyen de forma automtica una vez termina la ejecucin del script que los crea y utiliza.

Utilizacin de los objetos


Una vez creado un objeto ya se podrn utilizar (si su visibilidad lo permite) y modificar sus propiedades y tambin las funciones o mtodos de su clase. Los mtodos se invocan mediante la siguiente sintaxis: $objeto->funcion() o $objeto->funcion(p,q) o $objeto->funcion(p)

dnde $objeto es el objeto creado en la instruccin anterior, el -> es obligatorio, funcion es el nombre de uno de los mtodos o funciones definidos en la clase invocada y donde los () son obligatorios y adems como ocurra en las dems funciones PHP puede contener valores, variables, etctera separadas por comas. Las propiedades (siempre que su visibilidad lo permita) son accesibles mediante: $objeto->propiedad o $objeto->propiedad=valor

En el primer caso estaramos leyendo el valor de esa propiedad y en el segundo le estaramos asignando el incluido despus del signo igual.

<?php /* incluimos el fichero que contiene la clase que pretendemos utilizar */ include('ejemplo299.php'); /* creamos un objeto utilizando el nombre exacto de la clase*/ $MiObjeto1=new MiClase; //no lleva parntesis /* leeremos los valores de las propiedades */ print "<br />Valor por defecto de la propiedad factor1: "; /* solo podremos leer desde aqu la propiedad publica factor1 Las propiedades privadas y protegidas solo son accesibles desde la propia clase y aqu estamos haciendo desde uno objeto que la instancia */ print $MiObjeto1->factor1; print "<br />Aplicacin del mtodo calcula "; print "<br />No pasamos argumentos. Por tanto calcula con 'a'=3 y 'b'=5: "; print $MiObjeto1->calcula(); print "<br />Pasamos 15 como argumento por tanto calcula con 'a'=15 y 'b'=5: "; print $MiObjeto1->calcula(15); print "<br />Pasamos 125 y -98 como argumentos por tanto calcula con 'a'=125 y 'b'=98: "; print $MiObjeto1->calcula(125,-98); /* solo podemos modificar desde aqu la propiedad factor1. Las otras dos por su carcter privado y restringido solo podran ser modificadas desde dentro de la propia clase o de una clase extendida */ print "<br />Modificamos el valor de la propiedad factor1: "; $MiObjeto1->factor1=196; print$MiObjeto1->factor1; print "<br />Clculo con los nuevos valores por defecto: "; print $MiObjeto1->calcula(); print "<br />Clculo con nuevos valores por defecto pero asignando a 'a' el valor 25: "; print $MiObjeto1->calcula(25); print "<br />Clculo con nuevos valores por defecto con 'a'=15 y 'b'=-8: "; print$MiObjeto1->calcula(15,-8); /* creamos un nuevo objeto y comprobamos que la modificacin de la propiedad factor1 no afectar al nuevo objeto (la modificacin se hizo en el objeto anterior no en la clase) */ $MiObjeto2=new MiClase; print "<br />Clculo con valores por defecto del nuevo objeto: "; print $MiObjeto2->calcula(); print "<br />Clculo con valores por defecto del objeto anterior: "; print $MiObjeto1->calcula(); /* destruimos el primero de los objetos aunque no sea necesario hacerlo. Al finalizar el script se destruira de forma automtica */ $MiObjeto1=null; ?>
ejemplo300.php

En este otro ejemplo trataremos de ver el comportamiento de los mtodos y propiedades de carcter no pblico.

<?php /* crearemos una clase con los diferentes tipos de variables y mtodos */ class Coche{ /* las propiedades han de tener especificada su visibilidad */ public $potencia="135 C.V."; public $tipo_iva="33"; private $precio="24535 euros"; protected $modelo="HF345"; /* un mtodo publico ya que no especificamos visibilidad */ function precio_final(){ return (int)($this->precio)*(1+$this->tipo_iva/100); } /* un mtodo privado al que solo podremos acceder desde la propia clase*/ private function precio_amigo($descuento=15){ return $this->precio_final()*(1-$descuento/100); } /* un metodo publico que nos lleva a otro privado. La funcion siguiente es accesible por su condicin de pblica. Ella puede acceder a las funciones privadas de la propia clase. Asi que le pedimos que "se cuele" por "la puerta trasera" en el mtodo precio_amigo y nos devuelva el resultado */ function puerta_trasera($porcentaje){ return $this->precio_amigo($porcentaje); } /* un metodo publico que accede a una propiedad privada. No podemos cambiar precios directamente porque estn en una variable privada. Pero esta funcin pblica si tiene acceso a cualquier propiedad o mtodo de su clase. La utilizamos para cambiar el precio */ function cambia_precios($precio){ $this->precio=$precio; } } /*Hasta aqu la clase. Ahora toca instanciar objetos de la clase Coche */ $MiNuevoCoche= new Coche; /* visualizamos sus propiedades publicas */ print "<br>La potencia es: ".$MiNuevoCoche->potencia; print "<br>El tipo de IVA es: ".$MiNuevoCoche->tipo_iva; print "<br>No puedo conocer el modelo. Es una propiedad absurdamente protegida"; print "<br>Tampoco puedo acceder al precio. Es una propiedad privada"; print "<br>Cambio el precio: a 100 euros"; $MiNuevoCoche->cambia_precios('100 euros'); print "<br>Compruebo el precio final: ".$MiNuevoCoche->precio_final(); print "<br>El precio de amigo (25% descuento)es: ".$MiNuevoCoche->puerta_trasera(25); /* instanciemos un nuevo objeto. Al nuevo cliente no le afectarn las modificaciones anteriores */ $TuNuevoCoche= new Coche; print "<br>Para el nuevo objeto el precio final: ".$TuNuevoCoche->precio_final(); ?>
ejemplo298.php

Constructores y destructores
Un constructor es una funcin que se ejecuta de forma automtica cada vez que se instancia un nuevo objeto. Para que PHP considere a una funcin como tal ha de estar definida en la propia clase y adems debe tener por nombre la palabra reservada __constructque tal como puedes ver comienza por dos guiones bajos. Cuando est definido, el constructor la instancia del nuevo objeto puede hacerse de una de estas formas: $objeto=new nombre_clase;

No difiere en nada de la comentada anteriormente. El constructor usuar como valores de las variables que necesite utilizar los definidos en la propia funcin __construct y/o los valores de la propiedades establecidas en la propia clase. $objeto=new nombre_clase (valor1, valor2, ...)

En este caso se incluyen, dentro del parntesis, los valores que deben asignarse a una o varias de las variables que requieran ser utilizadas por la funcin __construct. Cuando se le pasan valores la funcin se ejecuta sin tomar en consideracin los asignados por defecto y cuando se le pasan slo parte de esos valores utiliza los valores recibidos y para los no asignados en la llamada utiliza los valores delconstructor. Un destructor es tambin una funcin que se ejecuta de forma automtica cada vez que se destruye objeto. Esa funcin ha de estar definida en la propia clase con el nombre __destruct (tambin comienza por dos guiones bajos). Hemos de tener en cuenta que esta funcin no destruye el objeto. Simplemente se ejecuta cuando se produce esa destruccin. Podramos decir que es algo as como un timbre de alarma. El timbre no provoca el incendio. Lo nico que hace es sonar cuando se produce uno. Los objetos van a dejar de ser necesarios cuando se finalice la ejecucin de un script. Al llegar a ese punto ser cuando, de forma autmatica, se libere la memoria usada para contenerlos y como consecuencia de ello se destruyan. Al producirse ese evento (liberacin de memoria) ser cuando se ejecute la secuencia de instrucciones contenidas en la funcin __destruct. Tambin podramos destruir un objeto en cualquier punto del proceso por medio de $objeto= null o unset($objeto) tal como ya hemos comentado. El objeto $objeto sera eliminado de la memoria y como consecuencia de esa destruccin se ejecutara de forma automtica la funcin __destruct. Aqu tienes un ejemplo de una clase que incluye un constructor y un destructor.

<?php class Operador1{ public $factor1=7; // esta es pblica private $factor2=8; // variable privada protected $factor3=3; // variable protegida function __construct($a=0,$b=0){ print "El constructor de MiObjeto".$a." ha fabricado esta fecha: "; print date("j-n-Y",(time()+($this->factor1+$b)*24*3600)); print "<br />"; } function opera($a=3,$b=46){ return $this->factor1-$b^2+$this->factor2*$a-$this->factor3; } function __destruct(){ print "O se acaba de destruir un objeto o me han llamado (soy __destruct)<br />"; } } ?>
ejemplo301.php

Si intentas ejecutar el ejemplo anterior no obtendrs ningn resultado. Slo es una clase. En este otro ejemplo instanciaremos esa clase y crearemos algunos objetos para tratar de comprobar el funcionamiento del constructor y el destructor.

<?php /* incluimos el fichero que contiene la clase que pretendemos utilizar */ include('ejemplo301.php'); /* creamos vaios objeto utilizando la clase que acabamos de incluir*/ $MiObjeto0=new Operador1; //no lleva parntesis y no incluye ningun valor $MiObjeto1=new Operador1(1); //solo lleva el primero de los parmetros del constructor $MiObjeto2=new Operador1(2,8); //incluye dos parmetros $MiObjeto3=new Operador1(3,98); /* llamo a la funcin destruct que pese a su nombre no destruye nada. Se llama as porque se ejecuta automticamente cuando un objeto deja de estar referenciado por una variable y se autodestruye. */ $MiObjeto0->__destruct();

print "El destructor no destruy. El objeto mantiene sus propiedades Este es factor 1: "; print $MiObjeto0->factor1."<br />"; print " Clculos en MiObjeto1. Empezamos por valores por defecto: "; print $MiObjeto1->opera(); print "<br />Clculo con valores por defecto pero asignando a 'a' el valor 25: "; print$MiObjeto1->opera(25); print "<br />Clculo con 'a'=15 y 'b'=-8: "; print$MiObjeto1->opera(15,-8); print "<br />Modificamos el valor de la propiedad factor1 en el objeto 1: "; $MiObjeto1->factor1=196; /* vamos a destruir MiObjeto2 y comprobaremos como al hacerlo se dispara automaticamente la funcion __destruct */ print "<br>Me van a borrar ahora mismo: "; $MiObjeto2 = null; print $MiObjeto1->factor1; print "<br />Clculo con los nuevos valores por defecto: "; print $MiObjeto1->opera(); print "<br />Clculo en MiObjeto3 pero asignando a 'a' el valor 25 al objeto 3: "; print $MiObjeto3->opera(25); print "<br />Clculo con nuevos valores por defecto con 'a'=15 y 'b'=-8 al objeto 4: "; print $MiObjeto3->opera(15,-8); print "<br />Vamos a acabar el script. Lo objetos se autodestruirn y aparecern los mensajes alusivos a eso.<br />"; print "Quedan tres objetos y tres autodestrucciones. Cada una de ellas disparar la funcin __destruct<br />"; ?>
ejemplo302.php

Clases extendidas y clases finales


La herencia es otra de las razones de ser de la Programacin Orientada a Objetos. En PHP tambin tenemos la posibilidad de crearclases extendidas o clases derivadas de una clase padre. Su caracterstica ms importante es que pueden heredar todas las propiedades y mtodos de esta y, adems, tienen la posibilidad de agregar otros nuevos y/o modificar o redefinir los heredados (polimorfismo).

Sintaxis de las clases extendidas


Para definir una clase clases extendida se requiere la siguiente sintaxis: class hija extends padre { .... ... definicin o redefinicin de variables (opcional).... .... .. constructores (opcional)... .... .. definicin o redefinicin de funciones (opcional)... .... }

dnde hija es el nombre de la nueva clase (la extendida), padre es el nombre de la clase padre y extends es la palabra reservada que indica a PHP que se trata de una clase extendida. Se puede impedir que una clase pueda extenderse. Para ello basta con anteponer a la palabra class la palabra final. Si escribimos: final class nieta extends hija {.....}

estaremos imposibilitando que puedan definirse clases extendidas de la clase nieta. Las restricciones de PHP 5 en lo relacionado con las herencias son las que puedes ver en este grfico:

Este es un ejemplo de clase extendida de una de las anteriores. Si intentas ejecutar el script te dar un mensaje de error advirtiendo de que no encuentra la clase padre. En este caso es irrelevante dado que el documento solo tiene la finalidad de escribir la clase extendida.

<?php /* esta clase no podra ser extendida y es hija de la llamada Operador1. Heredar de ella sus mtodos y sus propiedades. Podr modificarlos y tambin incluir los propios */ final class Operador2 extends Operador1{ /* modificamos esta propiedad cambiando su valor */ public $factor1=297; // esta es pblica /* aadimos una nueva propiedad */ public $factor4=-67; /* Este es el constructor de la clase extendida. Sustituira al de la clase padre */ function __construct(){ print "Soy el constructor extendido y punto.<br>"; } /* redefinimos la funcin opera. Dar otros resultados */ function opera($a=3,$b=46){ /* utilizaremos solo factor1 y factor3 porque son los nicos visibles desde esta clase. factor1 por su condicin de pblico y factor3 porque su condicin de protegido le hace tambin visible desde la clase extendida */ return $this->factor1-$a^2+$this->factor3*$b+$this->factor3; } /* omitimos la funcin __destruct pero podremos usar la definida en la clase padre */ function nueva(){ print "Soy el resultado de una nueva funcin. <br />"; } } ?>
ejemplo303.php

Aqu tienes un ejemplo de utilizacin de algunas de las posibilidades de la clase extendida anterior. Ahora ya incluimos ambas clases (padre y extendida) y no tendremos mensajes de error al ejecutar el script.

<?php /* hemos de incluir los ficheros que contienen ambas clases */ include('ejemplo301.php'); include('ejemplo303.php'); /* crearemos un objeto instanciando la clase padre y otro instanciando la extendida*/ $Objeto_de_clase_padre=new Operador1; /* este primer objeto no va a tomar en cuenta nada de lo contenido en la clase extendida*/ $Objeto_de_clase_extendida=new Operador2; /*este segundo objeto ya va a utilizar el constructor de la clase extendida. Al ejecutar el script podrn verse las diferencias */ print "<br>Este el valor del factor1 en el objeto creado a partir de la clase padre: "; print $Objeto_de_clase_padre->factor1; print "<br>Este el valor del factor1 en el objeto creado a partir de la clase extendida: "; print $Objeto_de_clase_extendida->factor1; /* la funcin (mtodo) nueva solamente puede ser usada en objetos creados mediante la clase extendida ya que para la clase padre no est definida. */ print "<br>Soy el resultado de la funcion nueva() aplicada al objeto de la clase extendida: "; $Objeto_de_clase_extendida->nueva(); /* la funcin (mtodo) opera es distinta segn el objeto pertenezca a una u otra clase. */ print "<br>Soy el resultado de la funcion opera() aplicada al objeto de la clase padre: "; print $Objeto_de_clase_padre->opera(); print "<br>Soy el resultado de la funcion opera() aplicada al objeto de la clase extendida: "; print $Objeto_de_clase_extendida->opera(); print "<br>Esta es la ltima instruccin del script. Lo que leas de aqu en adelante "; print "ser obra de los destructores que se activarn al destruirse los dos objetos<br>"; ?>
ejemplo304.php

Bibliotecas de clases
Una de las ventajas ms importantes de las clases es la posibilidad de reutilizacin de sus scripts tanto si se trata de rutinas propias o de desarrollos de terceros. Bastara con disponer del fichero que contiene la clase correspondiente conocer sus mtodos pblicos (los nicos accesibles de la forma que lo hemos hecho en los ejemplos anteriores) y utilizarlos con la sintaxis que hemos venido usando en los ejemplos anteriores. Existen algunos sitios en la red en los que pueden obtener una gran cantidad de materiales de este tipo. Uno de los ms populares puedes encontrarlo en la direccin: phpclasses.org. Adems existen otros sitios dnde se pueden obtener algunas clases muy interesantes. Cuando tratemos lo relativo a ficheros en formato PDF veremos el enorme abanico de posibilidades que nos ofrece la clase TCPDF. Por el momento, para intentar ilustrar un poco la utilizacin de clases de terceros, incluimos un ejemplo que permite el envo de mensajes de correo con ficheros adjuntos (similares a los que hemos podido ver al tratar el tema de mensajes de correo) utilizando la clase phpmailer. Pese a que el enlace de descarga incluye abundante material y documentacin solo hemos extraido de l los dos ficheros que necesitamos para el ejemplo: class.phpmailer.php y class.smtp.php que podemos utilizar de la siguiente forma:

<?php /* evito con esta opcin init_set evitamos queaparezca un mensaje de advertencia relativo a una funcin utilizada en la clase y que est deprecated */

ini_set('display_errors','Off'); /* incluimos el fichero que contiene la clase llamada PHPMailer */ require("class.phpmailer.php"); /* creamos un nuevo objeto (mi_mensaje) instanciando la clase PHPMailer*/ $mi_mensaje = new PHPMailer(); $mi_mensaje->IsSMTP(); // este metodo publico especifica el tipo de servidor a utilizar (SMTP) /* asignamos valores a una serie de propiedades (variables) de la clase */ $mi_mensaje->Host = "127.0.0.1"; //modificamos la propiedad Host asignandole la IP del servidor $mi_mensaje->From = "juan@mispruebas.as"; // Correo del remitente asignado a al propiedad From $mi_mensaje->FromName = "Juan Mis Pruebas"; // nombre del remitente a la propiedad FromName $mi_mensaje->AddAddress("perico@mispruebas.as", "Perico Mis Pruebas"); // un destinatario $mi_mensaje->AddAddress("andres@mispruebas.as"); // otro destinatario el nombre es opcional $mi_mensaje->AddReplyTo("juan@mispruebas.as", "Juan Mis Pruebas"); //direccin de respuesta $mi_mensaje->WordWrap = 50; // longitud de la lnea del mensaje $mi_mensaje->Subject = "Prueba con adjuntos usando la clase phpmailer"; //Asunto $mi_mensaje->Body = "Este es un mensaje de prueba con ficheros adjuntos que usa la clase phpmailer"; //cuerpo $mi_mensaje->AltBody = "Este es un mensaje de prueba con ficheros adjuntos que usa la clase phpmailer"; //cuerpo cuando no utiliza HTML /* aplicamos al objeto los mtodos (funciones) de la clase necesarios para nuestro propsito */ $mi_mensaje->IsHTML(true); // enviar mensaje con formato html $mi_mensaje->AddAttachment("apachito.zip"); // aadir adjunto $mi_mensaje->AddAttachment("casa08.jpg", "leocadio.jpg"); // adjunto con nombre /* aplicamos al objeto el mtodo Send y comprobamos si tod se ha realizado correctamente */ if(!$mi_mensaje->Send()){ echo "El mensaje no ha podido enviarse. <br />"; echo "Error al enviar el mensaje: " . $mi_mensaje->ErrorInfo; exit; }else{ echo "El mensaje ha sido enviado"; } ?> Cuidado! No olvides que para ejecutar este script es imprescindible que tengas activo tu servidor de correo.

Como habrs podido ver, la nica dificultad que nos plantea el uso de esta clase es conocer los mtodos y propiedades que incluye y la utilidad de los mismos. Ese tipo de informacin suele venir incluida como comentarios dentro de la propia clase y/o en la documentacin relativa a la misma.

Uso de la clase phpmailer mediante el SMTP de gmail


Para enviar mensajes de correo externos utilizando el SMTP de Gmail slo es necesario disponer de una cuenta de usuario en Gmail y agregar o sustituir en el script del ejemplo anterior lo siguiente: $mi_mensaje->Host = 'ssl://smtp.gmail.com'; $mi_mensaje->Port = 465;

$mi_mensaje->SMTPAuth = true; $mi_mensaje->Username = 'direccion_completa_de_la_cuenta_de_gmail'; $mi_mensaje->Password = 'contrasea_de_la_cuenta_de_gmail'; $mi_mensaje->From = 'direccion_completa_de_la_cuenta_de_gmail';

Como es obvio, adems de tener en marcha el servidor Apache en modo local es preciso que nuestro equipo disponga de acceso a Internet.

Clases y objetos (II) Constantes. Variables y mtodos estticos


En la pgina anterior slo hemos visto una parte de las opciones de definicin y uso de clases y objetos. Intentaremos ampliar un poco ms aquellos conceptos.

Constantes
Uno de los elementos no imprescindibles que puede contener una clase son las constantes. Para definirlas debemos escribir: const nombre = valor

dnde const es una palabra reservada que establece la condicin de constante, nombre es el nombre de la propia constante (no va precedido de $) y valor el nmero o cadena alfanumrica asignada a esa constante.

Variables estticas y mtodos estticos


Las propiedades que hemos estudiado en la pgina anterior son conocidas como propiedades y tambin como variables de objeto. Sin embargo pueden definirse otro tipo de variables conocidas como variables de clase, variables estticas o simplemente estticas. Se caracterizan por ser inherentes a la propia clase pudiendo existir y ser utilizadas sin necesidad de instanciar ningn objeto. Es decir, no forman parte de los objetos. A modo de ejemplo podramos decir que entre las propiedades de una perforada puede estar la de hacer funciones de cascanueces y que para hacer uso de esta propiedad (partir una nuez) no se requiere de ninguno de los objetos especficos (hojas de papel o cualquier otro objeto susceptible de ser perforado) para los que fu diseada la perforada (la clase). Son ese tipo de propiedades inherentes a la propia clase y que no requieren de un objeto para ser utilizadas las conocidas comoestticas. Para definirlas basta anteponer al nombre de la propiedad la palabra reservada static. La sintaxis podra ser as: static nombre = valor

La condicin de esttica de una propiedad no es incompatible con la gestin de su visibilidad. Es perfectamente factible utilizar variables definidas como: public static, private static reserved static. Por una cuestin de compatibilidad con PHP4 en los casos en los que solo se indique static tendr la consideracin de public static. Aqu tienes algunos ejemplos de definiciones vlidas: public static $pepe="Jose" static $lola="Dolores" private static $rosa="Rosa"

Por lo que respecta a mtodos estticos (tampoco requieren definir un objeto para poder utilizarlos) la sintaxis es similar a la anterior.

Acceso a constantes y a variables y mtodos estticos


Las variables estticas, las constantes y los mtodos definidos como estticos tienen la peculiaridad de que pueden ser utilizadossin necesidad de haber creado o instanciado ningn objeto. Para acceder a ellos se usa, en vez del tradicional ->, el operador :: conocido como doble dos puntos, operador de resolucin de mbito o Paamayim Nekudotayim Para acceder a este tipo de variables y/o constantes sin instanciar un objeto debemos utilizar la siguiente sintaxis: $variable1= nombreClase::constante

recoge en $variable1 el valor de la constante establecida en la clase nombreClase. Los caracteres (::) son obligatorios y reservados. $variable2= nombreClase::$variable_estatica

recoge en $variable2 el valor de la $variable_estatica correspondiente a la clase nombreClase. Los caracteres (::) son obligatorios y reservados. El nombre de la variable, a diferencia de lo que ocurre con variables no estticas, debe ir precedido del carcter $. $variable3= nombreClase::metodo_estatico()

recoge en $variable3 el resultado de la ejecucin del netodo_estatico() correspondiente a la clase nombreClase. Los caracteres (::) son obligatorios y reservados. El parntesis puede incluir eventuales valores de los argumentos de la funcin. Si lo que pretendemos es acceder a la variables o mtodos estticos a partir de una instancia de objeto perteneciente a su clase utilizaremos la sintaxis: $objeto :: constante , $objeto :: variable_estatica o $objeto :: metodo_estatico()

y en el caso de ejercer esta opcin desde un mtodo de la propia clase lo haramos con la misma sintaxis pero sustituyendo $objetopor el pseudobjeto $this. Cuando el acceso a constantes, variables o mtodos estticos se produce desde un mtodo de la propia clase puede sustituirsenombreClase por la palabra reservada self (yo mismo). Obsrvalo en los ejemplos. Este primero gestiona nicamente constantes y elementos estticos.

<?php class MiClase { /* definimos constantes */ const cadena1="Soy una cadena"; const cadena2=1.234; /* aqui usamos sintaxis de documento incrustado */ const cadena3=<<<'cde' Soy una cadena incluida dentro de una constante mediante la sintaxis de documento incrustado. Esta sintaxis funciona siempre que la versin de PHP sea superior a 5.3 cde; /* definimos una variable esttica */ public static $estatica=<<<'fdg' Soy una variable esttica y soy pblica. Tanto yo como las constantes podemos ser visualizadas sin necesidad de crear un objeto. Utilizando :: puede vrseme sin problemas. fdg; /* incluyamos dos funciones definidas como estticas */

public static function mi_estatica($a,$b){ return pow($a, $b)*self::cadena2- MiClase::otra_estatica($a,$b); } public static function otra_estatica($a=3,$b=2){ return pow($b, $a) + MiClase::cadena2; } } /* he escrito la clase pero no voy a crear ningn objeto. Visualizo los elementos y ejecutar los mtodos estticos */ print MiClase::cadena1."<br />"; print MiClase::cadena2."<br />"; print MiClase::cadena3."<br />"; print MiClase::$estatica."<br />"; print MiClase::mi_estatica(6,5)."<br />"; print MiClase::otra_estatica()."<br />"; ?>
ejemplo306.php

Cuidado! La sintaxis de documento inscrutado no funciona en versiones de PHP inferiores a la 5.3. Ocurre lo mismo con $objeto :: constante , $objeto :: variable_estatica o $objeto :: metodo_estatico() que en versiones inferiores han de ser sutituidos por: Nombre_de_la_Clase::constante , Nombre_de_la_Clase::variable_estatica oNombre_de_la_Clase::metodo_estatic o()

En este otro ejemplo estamos mezclando llamadas a variables y mtodos estticos junto con otros que lo no son. Todos tienen en comn la condicin de visibilidad pblica.

<?php /* definimos una clase */ class MiPagina { /* establecemos los valores de las constantes y las variables cuidando que todas estas sean publica */ const cabeza1="<html><head><title>"; static $titulo="Probando clases y objetos"; const cabeza2="</title></head><body bgcolor='"; public $color='yellow'; const cabeza3="'>"; public $cuerpo=<<<'CUERPO' Las clases en PHP permiten la sintaxis de <b>documento incrustado</b> solo a partir de la versin 5.3.<br /> En esta pgina utilizamos constantes y propiedades de tipo <b>public</b> (las estticas siempre lo son). Por esa razn son accesibles desde cualquier lugar.<br /> Modificaremos el <i>color de fondo</i> y el <i>ttulo</i>. CUERPO; public $pie="</body></html>"; /* en este caso la clase no incluye ningn mtodo */ } /* creamos un nuevo objeto instanciando esta clase */ $MiObjeto= new MiPagina; /* modificamos el color y el ttulo. Observa la diferente forma en que tratamos las variables estticas */ $MiObjeto->color='Coral'; /* cambiamos el valor de la variable esttica $titulo;

MiPagina::$titulo='Ha cambiado el titulo de esta pagina'; /* visualizamos los diferentes elementos (constantes, variables y variables estticas aplicando la sintaxis adecaduada a cada caso) */ print $MiObjeto::cabeza1; print $MiObjeto::$titulo; print $MiObjeto::cabeza2; print $MiObjeto->color; print $MiObjeto::cabeza3; print $MiObjeto->cuerpo; print $MiObjeto->pie; ?>
ejemplo307.php

Aqu tienes un tercer ejemplo en el se utilizan distintos tipos de visibilidades


ejemplo308.php Ver cdigo fuente

Mtodos y/o propiedades con el mismo nombre en clases extendidas


Cuando una clase incluye un mtodo o propiedad cuyo nombre coincide con el de otro mtodo o propiedad de una de sus clases extendidas los objetos utilizarn los mtodos o propiedades de la clase que ha sido instanciada para crearlos. Esta situacin, conocida bajo el nombre de polimorfismo (varias formas de un mismo mtodo) es algo muy habitual en la programacin orientada a objetos. Hay que tener en cuenta que cuando se trata de constantes, variables estticas o mtodos estticos que no requieren un objeto puede accederse indistintamente a los de una u otra clase por medio de la siguiente sintaxis: nombre_de_clase:: constante, variable o mtodo pudiendo tambin reemplazarse el nombre_de_clase por un objeto de esa misma clase. La cuestin es: puede accederse desde un objeto de una clase extendida a un mtodo de la clase padre cuano se da una coincidencia de nombres?. La respuesta es s. Una posibilidad es utilizar esta sintaxis: nombre_de_la_clase_padre :: nombre_del_metodo()

dnde se ejecutara el mtodo nombre_del_metodo() de la forma en que est definido en la clase nombre_de_la_clase_padre. Otra forma de hacerlo sera dotar a la clase extendida de un mtodo similar a este: function intermediaria () { return parent::metodo(); }

de esta forma la funcin intermediaria devolver (return) el resultado de ejecutar el mtodo de la clase padre (parent). Observa en el ejemplo los resultados las diferentes opciones.

<?php /* creamos las clases A, B extendida de A */ class A { /* habr en la clase extendida otra constante con const CONSTANTE=3.141592; /* Hay otra variable esttica con el mismo nombre public static $estatica="Soy la variable publica /* Hay otra variable publica con el mismo nombre public $variable=" Soy publica y de la clase A";

el mismo nombre CONSTANTE*/ (estatica) en la clase B */ esttica de la clase A"; (variable) en la clase B */

/* incluimos un contructor en la clase padre */ function __construct(){ print "<br><b>Se instanci un objeto de la clase A.</b> <br>"; } /* Hay otro metodo esttico con el mismo nombre (estatico )en la clase B */ public static function estatico(){ return "Me enva el mtodo esttico de la clase A (padre)"; } /* Hay otro metodo con el mismo nombre (metodo)en la clase B */ public static function metodo(){ return "Me llamo mtodo y soy de la clase A (padre)"; } } class B extends A{ /* Hay otra constante con el mismo nombre CONSTANTE en la clase A (padre)*/ const CONSTANTE=6.28; /* Hay otra variable esttica con el mismo nombre (estatica) en la clase A (padre)*/ public static $estatica="Soy una variable publica esttica de la clase B"; /* Hay otra variable publica con el mismo nombre (variable) en la clase A (padre) */ public $variable=" Soy publica y de la clase B"; /* incluimos un contructor en la clase extendida */ function __construct(){ print "<br><b>Se instanci un objeto de la clase B</b><br>"; } /* Hay otro metodo esttico con el mismo nombre (estatico )en la clase A (padre) */ public static function estatico(){ return "He surgido del mtodo esttico de la clase B"; } /* Hay otro metodo con el mismo nombre (metodo)en la clase A padre */ public static function metodo(){ return "Me llamo mtodo y soy de la clase B"; } /* Creo una funcion puente para poder acceder a mtodos de la clase padre que tienen un nombre coincidente con uno de de la extendida */ public static function puente(){ return parent::metodo(); } } /* creamos un objeto instanciando la clase A */ $objeto_clase_A= new A(); /* creamos un objeto instanciando la clase B */ $objeto_clase_B= new B(); print print print print print print print print print print "<br><br>LECTURA DE CONSTANTES<br>"; "<br>\$objeto_clase_A::CONSTANTE= ".$objeto_clase_A::CONSTANTE; "<br>\$objeto_clase_B::CONSTANTE= ".$objeto_clase_B::CONSTANTE; "<br>A::CONSTANTE= ".A::CONSTANTE; "<br>B::CONSTANTE= ".B::CONSTANTE; "<br><br>LECTURA DE VARIABLES ESTTICAS<br>"; "<br>\$objeto_clase_A::\$estatica= ".$objeto_clase_A::$estatica; "<br>\$objeto_clase_B::\$estatica= ".$objeto_clase_B::$estatica; "<br>A::\$estatica= ".A::$estatica; "<br>B::\$estatica= ".B::$estatica;

print "<br><br>LECTURA DE VARIABLES PUBLICAS<br>"; print "<br>\$objeto_clase_A->variable= ".$objeto_clase_A->variable; print "<br>\$objeto_clase_B->variable= ".$objeto_clase_B->variable; print "<br><br>EJECUCIN DE METODOS ESTATICOS<br>"; print "<br>\$objeto_clase_A::estatico()= ".$objeto_clase_A::estatico();

print "<br>\$objeto_clase_B::estatico()= ".$objeto_clase_B::estatico(); print "<br>A::estatico()= ".A::estatico(); print "<br>B::estatico()= ".B::estatico(); print print print print print clase print ?> "<br><br>EJECUCIN DE METODOS <br>"; "<br>\$objeto_clase_A->metodo()= ".$objeto_clase_A->metodo(); "<br>\$objeto_clase_B->metodo()= ".$objeto_clase_B->metodo(); "<br>A::metodo()= ".A::metodo(); "<br>Tambin podemos recurrir a la funcin puente para ejecutar el mtodo de la padre"; "<br>\$objeto_clase_B->puente()= ".$objeto_clase_B->puente();

ejemplo310.php

Funciones con clases y objetos


Existen tambin algunas funciones que pueden resultarte tiles a la hora de depurar los scripts en los que manejes clases y objetos. Son las siguientes: method_exists(objeto, nombre_funcion)

Comprueba si est definida la funcin nombre_funcion (entenderemos funcin y mtodo como sinnimos) en el objeto $objeto. Devuelve un valor booleano. Cierto (true) en el caso de que exista esa funcin o falso (false) en el caso de que no exista. get_class_vars(nombre_de_la_clase)

Crea un array asociativo cuyos ndices son los nombres de las propiedades de la clase nombre_de_la_clase y cuyos valores coinciden con los valores preasignados a cada una de esas propiedades. En este array solo se recogen las variables que han sidoinicializadas asignndoles un valor. get_class_methods(clase)

Devuelve un array conteniendo los valores de todos los mtodos (funciones) definidas en la clase. get_object_vars(objeto)

Devuelve las variables visibles (y sus valores) contenidas en el objeto.

Incluyendo clases desde ficheros externos


A lo largo de nuestros ejemplos hemos guardado muchas de las clases en ficheros independientes y posteriormente las hemos incluido en los script mediante las funciones include o require_once. No habra restriccin en cuanto al nombre a utilizar, sin embargo, resulta muy aconsejable fijar una metodologia simple y cmoda para hacerlo. Si establecemos la pauta de guardar siempre los ficheros que contienen una clase con el nombre de la propia clase (exactamente el nombre de la misma) seguido de una extensin que tambin vamos a mantener fija y que podra ser, por ejemplo, .class.php podemos hacer uso de una comodsima funcin (__autoload) que intentaremos concretar con el ejemplo y que comentamos en l. Hemos duplicado el fichero ejemplo299.php de la pgina anterior (aqu est su cdigo fuente) y lo hemos guardado comoMiClase.class.php porque MiClase es precisamente el nombre de la clase que contiene.

<?php

function __autoload($nombre_de_clase){ include $nombre_de_clase .'.class.php'; } /* esta funcion se encarga de que cada vez que sea instanciada una clase se cargue mediante include el fichero cuyo nombre coincide con el de la clase y cuya extensin es .class.php. De este modo ya podemos despreocuparnos de incluir clases. */ $objeto= new MiClase; /* se cargara la clase MiClase.class.php y se creara el objeto A partir de aqu comprobaremos los resultados de las diferentes funciones informativas visualizando sus resultados mediante print_r con lo cual estaremos en condiciones de visualizar de forma cmoda nombres de variables y/o mtodos y sus valores */ print "<br />Resultados de var_dump<br /><br /><pre>"; var_dump($objeto); print "</pre><br /><br />Resultados de print_r<br /><br /><pre>"; print_r($objeto); print "</pre><br /><br />Resultados de var_export<br /><br /><pre>"; var_export($objeto); print "</pre><br /><br />Resultados de get_object_vars<br /><br /><pre>"; print_r(get_object_vars($objeto)); print "</pre><br /><br />Resultados de get_class_methods<br /><br /><pre>"; print_r(get_class_methods($objeto)); print "</pre><br /><br />Resultados de get_class_vars<br /><br /><pre>"; print_r(get_class_vars('MiClase')); method_exists('MiClase','lee') ? print "<br>Existe el mtodo" : print "<br>No existe el mtodo"; method_exists('MiClase', 'calcula')? print "<br>Existe el mtodo" : print "<br>No existe el mtodo"; print "</pre>"; ?>
ejemplo309.php

Objetos nicos
La utilizacin de clases est ntimamente ligada a la creacin de objetos (en plural). Si pensamos en un centro de enseanza veremos que varias son las aulas, los profesores o los alumnos. Pero puede que nos planteemos que el centro como tal sea un objeto nico. Para aquellos casos en los que queramos impedir la creacin de ms de un objeto podra ser aplicable el procedimiento descrito en este ejemplo.

<?php /* escribiremos una clase cuyos nico objeto sea un centro educativo. Para poder utilizar la funcin __autoload el fichero tendr como nombre Centro.class.php que coincide con el nombre de la clase */ class Centro{ /* establecemos las propiedades con condicin de protegidas*/ protected $nombre="I.E.S. Las Pruebas y los Objetos"; //nombre del centro protected $identificador="Q337777777x"; //podra ser el N.I.F. protected $localidad="Fuentes de Narcea (Degaa)" protected $aulas=array(); // ser un array destinado a contener aulas (objetos de otra clase) /* insertamos un costructor con visibilidad protegida. As evitamos que pueda ser invocado desde fuera de la clase o de sus extendidas */ protected function __construct(){ print "Objeto creado satisfactoriamente<br>"; }

/* Agregamos una variable privada y estatica con valor nulo que solo ser visible desde la propia clase y no requerir un objeto para ser instanciada */ protected static $instancia; /* Incluimos un mtodo pblico y esttico con nombre Unico() que: Comprueba si la propiedad $instancia tiene valor. En caso de tenerlo nos da un mensaje de advertencia. Si no lo tiene crea un nuevo objeto de la clase actual. */ public static function Unico(){ if (!isset(self::$instancia)) { $objeto =__CLASS__; // __CLASS__ contiene el nombre de la clase actual self::$instancia = new $objeto; }else{ print "Ya existe un objeto Centro y ha de ser nico"; } return self::$instancia; //devuelve el objeto recien creado } } ?> <?php /* la funcion autoload nos permitir cargar la clase Centro que es la que se instanciar para crear el objeto */ function __autoload($clase){ include $clase.'.class.php'; } /* la sintaxis habitual \$objeto=mew Centro dara un mensaje de error ya que el mtodo __construct tiene el carcter de protected con lo cual se impide que puede ejecutarse desde esta opcin */ /* Lo nico visible de la clase Centro es el mtodo Unico. Dado que es un mtodo esttico habr que invocarlo con la sintaxis adecuada a su condicin */ Centro::Unico(); /* Al ser invocado por primera el mtodo Unico crea el objeto. */ Centro::Unico(); /* Cuando se invoca por segunda vez el mtodo Unico ya no puede crea el objeto y da el mensaje de advertencia. */ ?>
ejemplo311.php

Objetos mltiples
Aqu puedes ver el cdigo fuente de algunas clases que hemos creado y que utilizaremos para la creacin del mltiples objetos tal como puede verse en el ejemplo que hay a continuacin
Ver clase Centro Ver clase Aula Ver clase Alumnos Ver clase Profesores

<?php /* la funcion autoload nos evita problemas a la hora de incluir los ficheros que contienen las clases requeridas */ function __autoload($clase){ include $clase.'.class.php'; } /* creamos el objeto miCentro tal como se describe en los ejemplos anteriores */ $miCentro=Centro::Unico(); /* comprobemos el contenido del objeto */

print print print print

"<br>Estas son las propiedades del objeto miCentro<br>"; "<pre>"; var_dump($miCentro); "</pre>";

/* vamos a crear el objetos de la clase Aula si miras el cdigo fuente de la clase Aula.class.php vers que el contructor agrega el valor correspondiente al identificador de cada objeto por esa razn cuando instanciemos objetos Aula vamos a incluir como argumento el valor de ese identificador */ /* un array nos puede ser util para crear masivamente las aulas */ $nombre_aulas=array('1 A','2 C','4 F','3 B','1B A'); /* Leeremos este array e iremos creando nuevos objetos de la clase Aula incluyendo el identificador que requiere el constructor */ for ($i=0;$i<sizeof($nombre_aulas);$i++){ /* Haremos que los nuevos objetos sean elementos de un array escalar Para ello solo tenemos que agregar [] a misAulas y cada objeto creado pasar a ser un elemento de ese array */ $misAulas[]=new Aula($nombre_aulas[$i]); } /* comprobemos el contenido de los objetos */ print "<br>Comprobacin de los objetos misAulas<br>"; print "<pre>"; print var_dump($misAulas); print "</pre>"; /* con una estrategia similar podremos crear los objetos de la clase Alumnos Ahora al instanciar cada objeto incliremos su nombre y apellido */ /* estos son los datos para los objetos alumnos */ $nombre_alumnos=array('Ana','Benito','Carla','Dionisio','Esther', 'Fernando','Guiomar','Herminio','Isabel','Jenaro'); $apellidos_alumnos=array('Jimnez','Iglesias','Husillos','Gmez','Fernndez', 'Escapa','Daz','Casado','Blzquez','Alonso'); for ($i=0;$i<sizeof($nombre_alumnos);$i++){ $misAlumnos[]=new Alumnos($nombre_alumnos[$i],$apellidos_alumnos[$i]); } /* comprobemos el contenido de los nuevos objetos */ print "<br>Comprobacin de los objetos misAlumnos<br>"; print "<pre>"; print var_dump($misAlumnos); print "</pre>"; ?>
ejemplo313.php

La ejecucin de este script nos permite comprobar que efectivamente se han creado los objetos pretendidos pero tiene un par de deficiencias manifiestas. Los diferentes tipos de objetos carecen de relacin. Hemos creado un centro, aulas y alumnos pero no tienen relacin alguna. Sus clases son independientes entre s. Los alumnos podran ser de ese u otro centro y lo mismo podra ocurrir con las aulas. Un segundo problema es que una vez que finaliza la ejecucin del script los objetos se destruyen y se pierde toda la informacin relativa a ellos. Vamos a tratar de ver a continuacin como evitar esa prdida.

Serializacin de objetos
Toda la informacin relativa a un objeto puede se transformada en una cadena mediante la funcin:

serialize(nombre_del_objeto)

donde nombre_del_objeto indica el objeto que pretendemos serializar. Los resultados de la serializacin son susceptibles de ser guardados en un fichero. De esta forma (puedes verlo en el ejemplo) los objetos pueden estar disponibles para su uso posterior.

<?php /* para evitar reescribir incluimos el ejemplo anterior. Se ejecutar integramente */ include('ejemplo313.php'); /* visualizamos la serializacion de cada objeto */ print "<brEsta es la serializacin de misAlumnos<br>"; print serialize($misAlumnos); print "<brEsta es la serializacin de misAulas<br>"; print serialize($misAulas); print "<brEsta es la serializacin de misAulas<br>"; print serialize($miCentro); /* tambin podemos guardar cada objeto en una variable o en un array tal como hacemos en las instrucciones siguientes */ $serializado[] = serialize($misAlumnos); $serializado[] = serialize($misAulas); $serializado[] = serialize($miCentro); /* vamos a hacer una segunda serializacin. Serializaremos y guardaremos en una variable los contenidos del array resultante de la serializacin anterior */ $todo=serialize($serializado); /*guardaremos en un fichero (le ponemos como nombre Almacenado)la serializacin resultante */ file_put_contents('Almacenado', $todo); ?>
ejemplo314.php

Recuperacin de objetos serializados


Los objetos contenidos de las cadenas (o ficheros) que contienen el resultado de una o varias serializaciones pueden ser recuperados por medio de la funcin: $objeto_recuperado= unserialize($cadena_serializada)

donde $objeto_recuperado es el nombre que pretendemos asignar al objeto recuperado (no tiene por qu coincidir que el que tena en el momento de ser serializado) y $cadena_serializada una variable que contiene el resultado de la serializacin previa. Es necesario que estn disponibles las clases a las que pertenecen los objetos que pretendemos recuperar.

<?php /* la funcion autoload no va a incluir los ficheros con las clases necesarias */ function __autoload($clase){ include $clase.'.class.php'; } /* leemeos el fichero y recogemos su contenido en una variable */ $serializado = file_get_contents('Almacenado'); /* recuperamos la serializacin y visualizmos el contenido */ $todo_junto = unserialize($serializado); print "<pre>";var_dump($todo_junto);print "</pre>"; print "<br>Podemos leer el array mediante un bucle<br>"; for($i=0;$i<sizeof($todo_junto);$i++){

print "<pre>"; var_dump(unserialize($todo_junto[$i])); print "</pre>"; } ?>


ejemplo315.php

Objetos que contienen objetos


Las propiedades (variables) de los objetos pueden contener valores alfanumricos o numricos, arrays, objetos y tambin arrays cuyos elementos sean objetos. La forma de asignar valores a las propiedades puede tener alguna de las formas siguientes: $objeto -> propiedad=valor

es la forma ms sencilla. Se asigna un nuevo valor (numrico o alfanumrico) a la propiedad del $objeto. Como es lgico requiere la preexistencia del objeto. $objeto -> propiedad [ ] = valor

Se asigna un nuevo valor (numrico o alfanumrico) a la propiedad [] del $objeto . Como es lgico la propiedad habr sido definida como array escalar en su clase y el resultado sera un nuevo elemento cuyo ndice se conformara de forma automtica sumando una unidad al del ltimo existente. $objeto -> propiedad = $otro_objeto

se asigna $otro_objeto (objeto preexistente de otra clase) como valor de la propiedad del $objeto . $objeto -> propiedad [ ] = $otro_objeto

se asigna $otro_objeto (objeto preexistente de otra clase) como valor de la propiedad del $objeto . El hecho de la propiedad tenga forma de array significa que $otro_objeto ser el valor asignado a un nuevo elementos del array. $objeto -> propiedad[] =new clase_del_objeto_a_incluir()

tambin en este caso se asigna un objeto como valor de la propiedad del $objeto . La diferencia estriba en que el objeto aadido no existe previamente. Por esa razn se crea en el momento de la inclusin mediante new seguido de clase_del_objeto_a_incluir() con los eventuales argumentos que pudiera requerir el constructor de la nueva clase. $objeto -> propiedad [ ] =new clase_del_objeto_a_incluir()

su nica diferencia con el caso anterior es que ahora el nuevo objeto ser almacenado en un array. En estos enlaces puedes ver el cdigo fuente de las clases utilizadas en el ejemplo que se incluye a continuacin de ellos.
Ver clase Centro Ver clase Aula Ver clase Alumnos Ver clase Profesores

<?php /* la funcion autoload nos evita problemas a la hora de incluir los ficheros que contienen las clases requeridas */ function __autoload($clase){ include $clase.'.class.php';

} /*creamos un nuevo objeto asignndole valor al identificador al instanciar de la clase Aula Puedes visualizar el constructor desde enlace que hay aqui encima */ $miAula=new Aula('Primero B'); /* la propiedad profesor va a contener un objeto de la clase Profesores que crearemos incluyendo los argumentos que utiliza su constructor */ $miAula->profesor=new Profesores('Juan','Lpez','Matemticas'); /* agregamos un nuevo elemento al array materiales */ $miAula->materiales[]="Pizarra digital"; /* modificamos el nmero de puestos ecolares del aula */ $miAula->puestos=45; /* haremos una inclusin masiva de objetos de la clase Alumnos (tambin puedes ver en el enlace el cdigo fuente de esta clase) utilizamos como valores los nombres y apellidos contenidos en los array */ $nombre_alumnos=array('Ana','Benito','Carla','Dionisio','Esther','Fernando','Guiomar'); $apellidos_alumnos=array('Jimnez','Iglesias','Husillos','Gmez','Fernndez','Escapa','D az'); for ($i=0;$i<sizeof($nombre_alumnos);$i++){ /* la propiedad alumnos de la clase Aula es un array de ahi que incluyamos los nuevos objetos (Alumnos) en alumnos[] */ $miAula->alumnos[]=new Alumnos($nombre_alumnos[$i],$apellidos_alumnos[$i]); } /* Visualizamos el contenido de el objeto Aula que incluye otros objetos en sus propiedades */ print "<pre>"; print var_dump($miAula); print "</pre>"; ?>
ejemplo316.php

Manipulacin de objetos contenidos en objetos


En los ejemplos que incluimos a continuacin puedes ver, comentados, algos casos de manipulacin de objetos contenidos en otros objetos.

<?php class AulaExtendida extends Aula { function lista_profes(){ print $this->profesor->nombre; print $this->profesor->apellidos; } function lista_profes1(){ print $this->profesor->nombre; print $this->profesor->apellidos; print $this->profesor->materia; } function lista_alumnos(){ foreach ($this->alumnos as $indice=>$contenido){ print $contenido->nombre." ".$contenido->apellidos." ".$contenido>ruta."<br>"; } }

function modifica_alumnos($nom_act='',$ap_act='',$nom_nue='',$ap_nue='', $ruta_nue=''){ foreach ($this->alumnos as $ind=>$cont){ if($this->alumnos[$ind]->nombre==$nom_act && $this->alumnos[$ind]>apellidos==$ap_act){ if ($nom_nue !='')$this->alumnos[$ind]->nombre=$nom_nue; if ($ap_nue !='')$this->alumnos[$ind]->apellidos=$ap_nue; if ($ruta_nue !='')$this->alumnos[$ind]->ruta=$ruta_nue; } } } function borra_alumnos($nom_act='',$ap_act=''){ foreach ($this->alumnos as $ind=>$cont){ if($this->alumnos[$ind]->nombre==$nom_act && $this->alumnos[$ind]>apellidos==$ap_act){ unset($this->alumnos[$ind]); } } $this->alumnos=array_values($this->alumnos); } } /****** comienza una porcin de cdigo idntica a la del ejemplo anterior ******/ function __autoload($clase){ include $clase.'.class.php'; } $miAula=new AulaExtendida('Primero B'); //instanciamos la clase extendida para usar sus metodos $miAula->profesor=new Profesores('Juan','Lpez','Matemticas'); $miAula->materiales[]="Pizarra digital"; $miAula->puestos=45; $nombre_alumnos=array('Ana','Benito','Carla','Dionisio','Esther','Fernando','Guiomar'); $apellidos_alumnos=array('Jimnez','Iglesias','Husillos','Gmez','Fernndez','Escapa','D az'); for ($i=0;$i<sizeof($nombre_alumnos);$i++){ $miAula->alumnos[]=new Alumnos($nombre_alumnos[$i],$apellidos_alumnos[$i]); } /**** acaba el cdigo idntica a la del ejemplo anterior ****/ $miAula->lista_profes(); print "<br /><br />"; /* lista alumnos */ $miAula->lista_alumnos(); print "<br />"; /* modifica alumnos sin busqueda*/ $miAula->alumnos[2]->nombre="Heliodoro"; $miAula->alumnos[3]->apellidos="de los Ros"; /* modifica alumnos con busqueda*/ $miAula->modifica_alumnos('Ana','Jimnez','Mara Gertrudis','Cucaln',48); /* borra alumnos con bsqueda*/ $miAula->borra_alumnos('Benito','Iglesias'); $miAula->lista_alumnos(); print "<br />"; print "<pre>"; print var_dump($miAula); print "</pre>"; print "<br><br>"; foreach ($miAula->alumnos[1] as $propiedad=>$valor){

print $propiedad."....".$valor."<br>"; } print "<br><br>"; foreach ($miAula->alumnos as $indice=>$objeto){ foreach ($objeto as $propiedad=>$valor){ print $indice."...".$propiedad."....".$valor."<br>"; } } $miAula->lista_profes1(); ?>
ejemplo317.php

<?php function __autoload($clase){ include $clase.'.class.php'; } /* crearemos un objeto de la clase Aula */ $aula=new Aula('Aula Magna'); print "<br><i>El identificador del aula recien creada es</i>: ".$aula->identificador; /* creamos tres objetos de la clase Alumnos */ $alumno[0]=new Alumnos ('Juan Carlos', 'Rodriguez'); $alumno[1]=new Alumnos ('Feliciano','Perez'); $alumno[2]=new Alumnos ('Luisindo','Orcasitas'); print "<br /><br /><i>Los objetos del array alumnos son estos</i>: "; /* El primer bucle nos permite leer los elementos del array (objetos) y el segundo extrae el nombre de la propiedad y su valor */ foreach ($alumno as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; } } /* aadimos algunos objetos Alumnos a la propiedad alumnos de la clase Aula */ $aula->alumnos[]=$alumno[0]; $aula->alumnos[]=$alumno[1]; /* incluimos un nuevo objeto en el array alumnos de la clase Aula */ $aula->alumnos[]=new Alumnos ('Sindulfo','Yebra'); /* copiamos el objeto recien creado en un nuevo objeto */ $alumno[3]=$aula->alumnos[2]; print "<br /><br /><i>Los objetos de la propiedad alumnos de la clase Aula son estos</i>: "; foreach ($aula->alumnos as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; } } /* modificamos nombres de alumnos tanto en el array alumnos como en los objetos aula>alumnos */ $aula->alumnos[0]->nombre="Tcito Petronio"; $alumno[1]->nombre="Francisca Maria"; $alumno[3]->nombre="Iigo Francisco"; print "<br><br><br>La modificacin se produce en ambos lugares<br><br>"; print "<br /><br /><i>Los objetos del array alumnos despus de los cambios son</i>: "; foreach ($alumno as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; }

} print "<br><br><i>En la clase Aula vemos esto despus de los cambios:</i>: "; foreach ($aula->alumnos as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; } } /* eliminaremos algunos objetos. En un caso lo haremos en los de clase Aula y en otros en el array alumno */ unset($aula->alumnos[0]); unset($alumno[1]); unset($aula->alumnos[2]); print "<br><br><br>Despus de destruir objetos.<br>"; print "<br>Tcito e Iigo en el objeto de la Clase Aula"; print "<br>Francisca en el objeto alumnos"; print "<br><br><i>Los objetos del array alumno despus de eliminar foreach ($alumno as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; } } son</i>: ";

print "<br /><br /><i>Los objetos de la clase Aula despus de eliminar son estos</i>: "; foreach ($aula->alumnos as $indice=>$objeto){ print "<br>".$indice." "; foreach ($objeto as $propiedad=>$valor){ print "<i>".$propiedad."</i>: ".$valor."; "; } } ?>
ejemplo318.php

Clases y objetos (III) Sobrecargas de propiedades


Al hablar de la privacidad decamos que las propiedades privadas y protegidas nicamente son accesibles desde funciones incluidas en la propia clase (o en una clase extendida si es protected). Eso significara que opciones del tipo print $objeto>propiedad o $objeto->propiedad=valor solo funcionaran en el caso de que la propiedad tuviera condicin de pblica. En esas situaciones la solucin para acceder a las propiedades no visibles (private y protected) sera agregar dentro de la propia clase algo como esto: ...... public function lee_privado($propiedad){ return $this->propiedad } ......

que hara de intermediario y que mediante algo similar a: print $objeto->lee_privado(propiedad) nos permitira conocer el valor de tal propiedad. Mediante procedimientos similares podramos modificar valores, eliminar propiedades o comprobar su existencia.

Para simplificar este proceso disponemos de palabras reservadas que permiten que determinadas funciones se ejecuten, si estn incluidas en la propia clase, de forma automtica. Enumeraremos el comportamiento de algunas de ellas. public function __get($propiedad) { return $this->$propiedad; }

cuando incluimos una funcin idntica a esta en una clase (es imprescindible que tenga la condicin de public y que el nombre de la funcin sea __get) podemos despreocuparnos de si una propiedad es public o tiene la condicin de private, protected. En el momento que intentamos conocer el valor de una propiedad del objeto escribiendo: $objeto->propiedad se ejecutar (si es necesario) de forma automtica esa funcin y nos devolver el valor requerido. public function __set($propiedad,$valor) { $this->$propiedad=$valor; }

Una funcin idntica a esta (tambin es imprescindible la condicin de public y que el nombre de la funcin sea __set) nos permite asignar un valor a cualquier propiedad del objeto independientemente de que su condicin sea public, private o protected. En el momento que intentamos asignar un valor escribiendo: $objeto->propiedad=valor se ejecutar (si es necesario) de forma automtica esa funcin y asignar a la propiedad el valor indicado. public function __unset($propiedad) { unset ($this->$propiedad); }

Eliminar la propiedad cuando escribamos: unset ($objeto->propiedad) ejecutndose de forma automtica, cuando sea necesario, la funcin __unset. public function __isset($propiedad) { return isset($this->$propiedad); }

Devolver TRUE o FALSE (dependiendo de que exista o no exista la propiedad) cuando escribamos: isset($objeto>propiedad). En el ejemplo puedes ver el funcionamiento de estos mtodos incluso en los casos en los que los valores de las propiedades sean arrays u objetos.

<?php /* esta clase tiene como una finalidad la creacin de un objeto para pruebas lo nico que hace cuando es instanciada es asignar valores a las propiedades publicas a y b.*/ class ObjetoAuxiliar{ public $a; public $b; function __construct($a=7,$b=14){ $this->a=$a; $this->b=$b; } } /* esta nueva clase es la que usaremos para nuestras pruebas */ class Pruebas { protected $propiedad1="13"; protected $matriz=array('Uno','Dos','Tres'); protected $objeto; function __construct(){ $this->objeto=new ObjetoAuxiliar; }

/* esta funcion mgica __get nos permitir ver desde fuera de la propia clase los contenidos de sus propiedades protegidas y privadas */ public function __get($variable){ return $this->$variable; } /* esta funcion mgica __get nos permitir, desde fuera de la propia clase, asignar valores a sus propiedades protegidas y privadas */ public function __set($propiedad,$valor){ $this->$propiedad=$valor; } /* esta funcion mgica __unset nos permitir, desde fuera de la propia clase, eliminar propiedades protegidas y privadas */ public function __unset($propiedad){ print "Eliminando: ".$propiedad."<br />"; unset($this->$propiedad); } /* esta funcion mgica __isset nos permitir, desde fuera de la propia clase, comprobar si est definidan propiedades protegidas y privadas */ public function __isset($propiedad){ return isset($this->$propiedad); } } /* creamos un nuevo objeto de la clase pruebas */ $miObjeto=new Pruebas(); /* la propiedad1 es protected. Eso significa que solo se visualizara desde una funcin de la propia clase o de una de sus extendidas. Cuando al invocarla resulta no ser accesible PHP comprueba si est definido el mtodo __get en la clase. Si lo est lo ejecuta de forma automtica considerando la propiedad1 como parmetro de la funcin __get. Dado que esa funcin pertenece a la propia clase si puede leer la propiedad y devolver el resultado */ print $miObjeto->propiedad1."<br>"; /* comprobamos que __get funciona tanto cuando la propiedad contiene un array como cuando se trata de un objeto. */ print_r($miObjeto->matriz)."<br>"; print_r($miObjeto->objeto)."<br>"; /* comprobemos ahora la funcin mgica __set. Se comporta identica a la anterior con la diferencia de que ahora recoge como parmetros el nombre de la propiedad y el valor que se pretende asignar */ $miObjeto->propiedad1=7456; print $miObjeto->propiedad1."<br>"; $miObjeto->matriz=array(7,4,5,6); print_r($miObjeto->matriz)."<br>"; $miObjeto->objeto= new ObjetoAuxiliar(25,987); print_r($miObjeto->objeto)."<br>"; /* comprobamos que se pueden borrar propiedades con los tres tipos de valores */ unset($miObjeto->propiedad1); unset($miObjeto->matriz); unset($miObjeto->objeto); /* comprobamos la existencia de la propiedad utilizando de forma idntica a los casos anteriores la funcin mgica __isset */ if (isset($miObjeto->propiedad1)){ print "La propiedad1 si existe"; }else{ print "La propiedad1 no existe"; } ?>

ejemplo319.php

Cuidado! Presta atencin a la sintaxis de las funciones que hemos descrito. Observa que hemos utilizado $this>$propiedadcuando lo habitual en las funciones sera $this->propiedad. Si omitimos el $ nos dar error.

Clases y mtodos abstractos


Quiz nos sea de utilidad detenernos en un caso de la vida cotidiana. Pensemos en una ITV. Los inspectores han de seguir un protocolo que consiste en verificar el funcionamiento de: carroceria, gases, bocina, luces, suspensin, frenos, direccin, etctera, de cadavehculo y, posteriormente, emitir y firmar un documento acreditativo de los resultados de tal inspeccin. Este protocolo contiene (o puede contener) instrucciones precisas para emitir y firmar los documentos (se sigue el mismo procedimiento sea cual sea el tipo de vehculo). Nos encontramos ante dos situaciones distintas: especificaciones concretas (mtodos) para la burocracia y especificaciones abstractas para la parte tcnica. Nadie nos ha dicho an como inspeccionar una direccin o unas luces. Este protocolo inicial podramos entenderlo como una clase abstracta con mtodos abstractos. El inspector necesita con carcter imprescindible mtodos concretos para los diferentes tipos de vehculos. Si se trata de una motocicleta el mtodo de inspeccin ser radicalmente distinto al de un turismo y el de este ser tambin distinto al de un autobs. As pues, habr de contar como mtodos de comprobacin de cada uno de los elementos para cada una de las clases de vehculo. En nuestro argotdiramos que son necesarias clases extendidas: motocicleta, turismo y autobs, y adems, cada una de esas clases ha de disponer de mtodos para todas y cada una de las verificaciones: carroceria, gases, etctera. Dicho de otra forma: es imprescindible redefinir cada uno de los mtodos abstractos para cada una de las clases extendidas. Algo muy similar ocurre con la Programacin Orientada a Objetos.

Clases y mtodos abstractos


Para definir un mtodo como la condicin de abstracto hemos de utilizar la siguiente sintaxis: abstract protected function nombre_del_metodo () dnde la palabra reservada abstract especifica su condicin de abstracto, protected establece el carcter protegido del mismo y adems, con caracter imprescidible, la function nombre_del_metodo () ha de estar declarada pero no definida (observa que faltan las {} y el habitual contenido de ellas que realmente es lo que define el mtodo o funcin). Otra cuestin sumamente importante. Para que una clase pueda incluir un mtodo abstracto tambin ella ha de tener la condicin de abstracta. Es decir, no podemos definir un mtodo como abstracto sin que la clase que lo contiene lo sea. Para definir como abstracta una clase hemos de hacer utilizar la siguiente sintaxis: abstract class nombre_de_la_clase

una clase definida como abstracta puede no contener mtodos abstractos y propiedades con cualquier tipo de visibilidad. Por el contrario, un mtodo abstracto solo puede ser incluido en una clase abstracta.

Restricciones de las clases y mtodos abstractos


El uso de clases abstractas requiere tener muy presentes las siguientes cuestiones: Las clases abstractas no pueden ser instanciadas para crear objetos Los mtodos no abstractos y/o las propiedades de una clase abstracta slo son accesibles desde sus clases extendidas. Estonos obliga a definir clases extendidas. Los mtodos abstractos de una clase (abstracta) han de ser obligatoriamente redefinidos en todas sus clases extendidas. Cuando se redefine un mtodo abstracto en una clase extendida ha de hacerse con una condicin de visibilidad igual o ms permisiva a la que se estableci en la clase abstracta. Si un mtodo abstracto tiene condicin de protected slo puede ser redefinido como public (ms permisivo) o protected (igual de permisivo)

<?php

/*creamos una clase abstracta en la que incluimos mtodos tanto abstractos como no abstractos, variables y constantes. Los mtodo abstractos solo se declaran pero no se define lo que deben hacer cuando sean invocados */ abstract class Figuras{ /*incluimos los mtodos abstractos */ abstract protected function calculaArea(); abstract protected function calculaPerimetro(); /* los restantes metodos, propiedades y constantes de la clase */ const PI=3.141592; protected $tipo; public function Imprime($a,$b){ print "La ".$this->tipo." cuyos radios son: ". $a." y ".$b."<br />"; print "El area es:".$this->calculaArea($a,$b)."<br />"; print "El permetro es:".$this->calculaPerimetro($a,$b)."<br />"; } } /* las clases abstractas no pueden ser instanciadas para crear objetos. Por tanto es imprescindible una clase extendida */ class Redondas extends Figuras{ public function calculaArea($radio1=0,$radio2=''){ if ($radio2=='') $radio2=$radio1; return self::PI*$radio1*$radio2; } public function calculaPerimetro($radio1=0,$radio2=''){ if ($radio2==''){ $radio2=$radio1; return self::PI*2*$radio1; }else{ return self::PI*(3*($radio1+$radio2)sqrt((3*$radio1+$radio2)*($radio1+3*$radio2))); } } } /* instanciamos un objeto de la clase extendida (la abstracta no lo permitiria)*/ $circulo= new Redondas(); /* desde este objeto ya se puede llamar a mtodos de cualquiera de las clases */ $circulo->Imprime (5,5); ?>
ejemplo320.php

Interfaces
Las interfaces tienen un cierto paralelismo con las clases y mtodos abstractos pero ni su sintaxis ni su comportamiento son iguales. Podemos decir que una interface es un declaracin o lista de mtodos publicos no definidos que han de incluirse (y definirse) con carcter obligatorio en todas las clases que implementen esa interface. Desde una perspectiva utilitarista podramos entenderlas como una lista de obligaciones y tareas obligatorias (mtodos que han de incluirse en una clase) que imposibilitar el olvido ya que de no realizarse todas (omitir algn mtodo establecido en la interface) las instancias de la clase producirn un error. En una interface solo pueden incluirse mtodos (funciones) con visibilidad public y constantes.

Sintaxis de las interfaces

Para declarar una interface es necesario una sintaxis como esta: interface nombre_de_la_interface { public function nombre_de_una_funcion (argumento1, argumento2,...) public function nombre_de_otra_funcion (argumento1, argumento2,...) ....... const nombre = valor (opcional) }

Para utilizar interface es necesario una sintaxis como esta: class nombre_de_la_clase implements nombre_de_una_interface, nombre_de_otra_interface { /*TODOS los mtodos de nombre_de_una_interface */ public function nombre_de_una_funcion (argumento1, argumento2,...){ .......(cdigo del mtodo) ......... ................ } public function nombre_de_otra_funcion (argumento1, argumento2,...){ .......(cdigo del mtodo) ......... ................ } /* TODOS los mtodos de nombre_de_otra_interface */ ................ ................ }

Restricciones de las interfaces y sus clases


Cuando una clase usa ms de una interface hay que cuidar que estas no contengan mtodos con el mismo nombre. De darse esa circunstancia se producira un error. Hay que definir en la clase todos los mtodos de todas las interfaces que impelenta. Las constantes definidas en una interface se utilizan exactamente igual que las constantes de clase. Su nica particularidad es que que no pueden ser sobrescritas por una clase/interfaz extendidas.

<?php /* creamos una interface que solo puede contener mtodos publicos no definidos y constantes */ interface Figuras{ public function calculaArea(); public function calculaPerimetro(); const PI=3.141592; } /* una nueva interface que en este caso no incluye ninguna constante */ interface Cuerpos{ public function calculaVolumen(); } /* definimos una clase que implementa las dos interfaces (Figuras y Cuerpos) ello le obliga a definir todas las funciones declaradas en ambas clases Si hubiera dos funciones con el mismo nombre se producira una ambiguedad que generara un error */ class Redondas implements Figuras, Cuerpos{ public $tipo; public function calculaArea($radio1=0,$radio2=''){

if ($radio2=='') $radio2=$radio1; return $this::PI*$radio1*$radio2; } public function calculaPerimetro($radio1=0,$radio2=''){ if ($radio2==''){ $radio2=$radio1; return self::PI*2*$radio1; }else{ return self::PI*(3*($radio1+$radio2)sqrt((3*$radio1+$radio2)*($radio1+3*$radio2))); } } public function calculaVolumen($radio1=0,$radio2=''){ if ($radio2=='') { $radio2=$radio1; return 4/3*self::PI*pow($radio1,3); }else{ return 4/3*self::PI*$radio1*pow($radio2,2); } } } /* instanciamos objetos pertenecientes a la clase de la forma habitual. La constante PI definida en el interface es asumida como propia por la clase */ $circulo= new Redondas(); print "El area de la figura es: ". $circulo->calculaArea(5,5) ."<br>"; print "El perimetro de la figura es: ". $circulo->calculaPerimetro(5,5) ."<br>"; print "El volumen del cuerpo es: ". $circulo->calculaVolumen(5,5) ."<br>"; ?>
ejemplo321.php

Mtodos que manejan objetos o arrays


Los mtodos definidos en una clase pueden manejar objetos de la propia clase o de otra. Esta ltima posibilidad requiere disponer de un objeto de cada una de las dos clases y, adems, que en una de ellas se incluyan mtodos con esta sintaxis: function nombre_del_metodo ( Otra_Clase, $objeto_cualquier_nombre , $argumento1, $argumento2,...) { $objeto_cualquier_nombre->propiedad $objeto_cualquier_nombre->metodo ( $argumento1, $argumento2,...) } La utilizacin de estos mtodos requiere haber creado previamente un objeto de cada una de las clases que vamos a llamar$Objeto_Base y $Objeto_Externo. Con estas premisas la ejecucin de un mtodo requerira esta sintaxis: $Objeto_Base->nombre_del_metodo ($Objeto_Externo, argumento1, argumento2) los nombres corresponden a los anteriormente descritos y los argumentos incluidos en la llamada se corresponden con los eventualmente requeridos por el mtodo referenciado en la que hemos llamado Otra_Clase tal como puedes ver en este ejemplo. Tambin es posible pasar arrays a los mtodos de una clase y manejar sus contenidos mediante funciones incluidas en el mtodo. Para ello se requiere la siguiente sintaxis: function nombre_del_metodo ( array, $variable) { ......... funciones php que manejan el array $variable

......... }

dnde array es una palabra reservada que especifica la condicin de tal de lo recogido por $variable. El mtodo debe ser invocado de la forma siguiente: $objeto -> nombre_del_metodo( array('elemento1','elemento2',...) ) o, como es lgico $matriz = array('elemento1','elemento2',...); $objeto -> nombre_del_metodo ( $matriz )

<?php /* definimos una clase que llamaremos externa (ser la auxiliar) que incluye mtodos aritmticos. La funcion suma puede recibir valores como argumentos y, en caso de recibirnos modificar las propiedades de sumando1 y sumando 2 */ class Externa { public $sumando1=1; public $sumando2=2; function if ($a if ($b return } Suma($a='',$b=''){ !='') $this->sumando1=$a; !='') $this->sumando2=$b; $this->sumando1+$this->sumando2;

function Resta(){ return $this->sumando1-$this->sumando2; } function Multiplica(){ return $this->sumando1*$this->sumando2; } function Divide(){ return $this->sumando1/$this->sumando2; } } /* definiremos ahora una nueva clase (que ser la Base de nuestro ejemplo) con la peculiaridad de que sus mtodos hacen referencia a otra clase y a objetos de esa otra clase. En todos los mtodos de esta clase (con una excepcin que comentaremos) se incluyen como parmetros el nombre de la clase auxiliar (Externa), una variable que recibir los objetos de la clase Externa y los eventuales argumentos requeridos por la funcin que en el caso de la suma son dos */ class Base { function adicion (Externa $exterior, $a='',$b='') { /* este mtodo pasar el objeto exterior (recibido en la llamada) junto con los valores de las variables a y b. Devolver el resultado de ejecutar el mtodo Suma (de la clase externa) sobre el objeto exterior tambin de la clase externa */ return $exterior->Suma($a,$b); } function sustracion (Externa $exterior) { return $exterior->Resta(); }

function multiplicacion (Externa $exterior) { return $exterior->Multiplica(); } function division (Externa $exterior) { return $exterior->Divide(); } function cambia_a (Externa $exterior, $a) { return $exterior->sumando1=$a; } /* en este caso el objeto recibido en la peticin es una instancia de la propia clase Base y se le aplicar un mtodo (neperiano) definido en esta misma clase. */ function lee_logaritmo (Base $exterior,$a) { return $exterior->neperiano($a); } /* el mtodo neperiano que ser instanciados por anterior */ function neperiano($a){ return log($a); } /* esta funcin recibe como argumento un array que ser recogido por la funcin en la variable la_matriz y tratado como tal. Requiere obligatoriamente la palabra reservada array en la misma posicin que en las funciones anteriores incluyen el nombre de la clase a la que pertenece el objeto. Ahora podra decirse que el array la_matriz es un objeto de la clase array */ function lee_matriz (array $la_matriz){ print "El array tiene: ".sizeof ($la_matriz)." elementos<br>"; foreach ($la_matriz as $indice=>$valor){ print $indice." * ".$valor."<br>"; } } } /*manejo de las clases anteriores */ /* Creamos un objeto de cada de las dos clases */ $Objeto_Externo = new Externa; $Objeto_Base = new Base; /* el objeto base ejecuta sus mtodos incluyendo como argumentos el identificado del objeto externo junto con los eventuales argumentos*/ print "La suma es: ". $Objeto_Base->adicion($Objeto_Externo)."<br />"; print "La suma con parmetros es: ". $Objeto_Base->adicion($Objeto_Externo,25,89)."<br />"; print print print print />"; "Los valores pasados a la funcin producirn una modificacin "; "en los valores de las propiedades sumando1 y sumando 2 del Objeto_externo. "; " Esas nuevos valores se mantendrn en tanto no vuelvan a ser modificados.<br>"; "La suma con un parmetro es: ". $Objeto_Base->adicion($Objeto_Externo,749)."<br

print "La suma con un parmetro es: ". $Objeto_Base>adicion($Objeto_Externo,'',125)."<br />"; print "La diferencia es: ".$Objeto_Base->sustracion($Objeto_Externo)."<br />";

print "El producto es: ".$Objeto_Base->multiplicacion($Objeto_Externo)."<br />"; print "El cociente es: ".$Objeto_Base->division($Objeto_Externo)."<br />"; print "El nuevo valor de a: ".$Objeto_Base->cambia_a($Objeto_Externo,1013)."<br />"; print "La suma es: ". $Objeto_Base->adicion($Objeto_Externo)."<br />"; print "El logaritmo neperiano de 10 es: ". $Objeto_Base>lee_logaritmo($Objeto_Base,10)."<br />"; print "Probando un array<br> "; print $Objeto_Base->lee_matriz(array(13,27,128,945,'pepe'))."<br>"; ?>
ejemplo322.php

Crear ficheros PDF Creacin de ficheros PDF


Exiten varias opciones para la creacin mediante funciones PHP de ficheros en formato PDF. El abanico de posibilidades se extiende desde las aplicaciones de pago tales como PDFlib hasta las clases open source tales como FPDF o TCPDF, que amplia las prestaciones de la anterior y que ser la que utilizaremos para desarrollar los contenidos de este tema.

La clase TCPDF
La clase TCPDF est en constante evolucin. Por ello se van produciendo, con mucha frecuencia, continuas actualizaciones, correcciones de errores y mejoras. Las versiones ms recientes pueden encontrarse en este enlace. Hemos descargado desdehttp://www.tcpdf.org el fichero tcpdf_5_9_088.zip (la ltima versin disponible en el momento de elaborar estos materiales) y lo hemos descomprimido en nuestro directorio php. Durante la descompresin se cre de forma automtica un directorio llamado tcpdf en el que se incluyeron una serie de subdirectorios tales como: config, examples y fonts y una serie de ficheros entre los que podremos encontrar el denominado tcpdf.php que es el que realmente contiene la clase. La creacin de ficheros PDF mediante la clase TCPDF requiere que en los scripts se incluyan los ficheros: tcpdf.php, tcpdf_config.phpy spa.php que corresponden a la clase propiamente dicha, a su configuracin y al idioma en uso. Tales ficheros se encuentran en los directorios: tcpdf y en sus subdirectorios tcpdf/config y tcpdf/config/lang. Para mayor comodidad en el manejo hemos creado un fichero llamado tcpdf.inc.php que sirve para realizar la inclusin de los tres anteriores. Puedes ver aqu su contenido. Si los ficheros estuvieran en directorios distintos de los indicados habran de adecuarse las rutas absolutas incluidas en el ficherotcpdf.inc.php.

El constructor de la clase TCPDF


La clase incluida en el fichero tcpdf.php tiene por nombre TCPDF. Por tanto su uso requerir adems del necesarioinclude('tcpdf.inc.php') la creacin de un objeto mediante la sintaxis: $objeto= new TCPDF();

Al instanciar un nuevo objeto se ejecuta siempre el constructor (recuerda que un constructor es una mtodo con nombre __constructque se ejecuta de forma automtica el momento en que es creado un nuevo objeto) que en esta clase permite seis argumentos: orientacion,unidad de medida, formato, unicode, codificacin y diskcach. Por tanto, al instanciar la clase para crear el nuevo objeto podramos escribir:

$objeto= new TCPDF( orientacion, unidad_de_medida, formato, unicode, codificacion, disckcache );

dnde: orientacion admite dos valores: 'P' (normal Portrait) y 'L' (apaisado Landscape en denominacin inglesa). El valor por defecto es 'P' (normal). unidad_de_medida permite especificar las dimensiones del documento en: 'in' (pulgadas), 'pt' (puntos), 'mm' (milmetros) y tambin 'cm' (centmetros). El valor por defecto es 'mm'' (milmetros). Recuerda que una pulgada equivale a 25,4 milmetros y queun punto equivale a 1/72 pulgadas (0,35277 mm.). formato permite especificar las dimensiones de cada pgina del documento mediante las convenciones de los formatos ISO 216 serie A desde 'A0' (841x1189 mm) hasta 'A12'; la serie B de ISO 216 desde 'B0' (1000x1414 mm) hasta 'B12' y la serie C de las misma norma desde 'C0' (917x1297 mm) hasta 'C12'. El valor por defecto es 'A4' (297x210 mm). unicode es un parmetro booleano (true o false) que permite indicar si los textos que se incluirn en el documento tendrn formato UNICODE o no. Por defecto su valor es TRUE codificacin permite indicar el formato de codificacin de los textos incluidos en el documento. Por defecto su valor es 'UTF-8'. diskcach es otro parmetro booleano que permite configurar el uso de la memoria RAM. Si est configurado como TRUE se utilizar menos memoria RAM almacenando los datos temporales en cach. El ahorro de memoria puede ralentizar fuertemente el proceso. El valor por defecto de este parmetro es false. Una vez creado el objeto es necesario aadirle una o ms pginas. Para ello se utiliza el mtodo AddPage. Su sintaxis ms simple es la siguiente: $objeto->AddPage()

Formatos a medida
La clase TCPDF tambin permite especificar formatos a medida. Para ello hemos definir las dimensiones deseadas mediante la sintaxis: $medidas=array(ancho,alto)

dnde ancho y alto son las dimensiones deseadas (especificadas en la unidad establecida para el documento) e incluir este array ($medidas) como valor del parmetro formato en la llamada al constructor de la clase.

El mtodo Output()
La clase TCPDF incluye la funcin Output que permite visualizar o guardar el objeto creado. Mediante la sintaxis: $obj->Output(nombre,destino)

puede asignarse cualquier nombre, con o sin extensin, al objeto generado. Cuando no se especifica el nombre, se le asigna por defecto el valor doc.pdf. El parmetro destino puede tener uno o varios de los siguientes valores: 'I' Permite visualizar el fichero directamente en el navegador si el plugin si est disponible. La opcin Guardar como... asignara, por defecto, el nombre especificado en el parmetro nombre. 'D' Enva el fichero al navegador mostrando la ventana de opcin que permite elegir entre Abrir o Descargar. Si se elige esta ltima, guardar el fichero con el nombre especificado en el parmetro nombre. 'F' Guarda el fichero en el directorio actual del servidor con el nombre asignado en la opcin nombre.

El mtodo SetDisplayMode()

Este mtodo slo afecta a la forma en la se visualiza el documento en la pantalla del cliente permite configurar dos parmetros:tamao y forma de visualizacin. $obj->SetDisplayMode( tamao,visualizacion)

El tamao (no se refiere al documento impreso sino a la visualizacin en pantalla) permite una de estas opciones: fullpage (el zoom del visor se adapta de modo que encaje la pgina completa en la pantalla); fullwidth (ajusta el zoom de forma que se visualize el documento ajustando el ancho al de la pantalla); real (ajusta el zoom del visor al 100%) default que usa el modo por defecto del visor. La forma de visualizacin permite, entre otras, las opciones: single muestras las pginas separadas de una en una; continuous va mostrndolas una detrs de otra de forma continua; two muestras dos columnas (con dos pginas) simultaneamente, y default que, como en el caso anterior, usa el modo por defecto del visor.

Algunsos ejemplos
Como primer ejemplo crearemos un fichero con dos pginas en blanco.

<?php # incluimos todos los ficheros requeridos # tal como lo hemos recogido en el fichero tcpdf.inc.php # creado tal como se indica al margen include("tcpdf.inc.php"); # creamos un nuevo objeto (MiPDF) utilizando la clase FPDF $MiPDF=new TCPDF(); # creamos una pgina en blanco $MiPDF->Addpage(); # creamos una segunda pgina en blanco $MiPDF->Addpage(); # visualizamos el documento $MiPDF->Output(); ?>
ejemplo323.php

Si observas con detalle el pdf del ejemplo anterior observars que en la parte superior de las pginas aparece una extraa lnea horizontal. Se debe a que, por defecto, esta clase incluye en cada documento un encabezado y un pie de pgina. La forma de evitarlo ser desactivar esa opcin incluyendo en el script llamadas a los mtodos setPrintHeader(false) y setPrintFooter(false) con el valor booleanofalse tal como puedes ver en este otro ejemplo.
ejemplo324.php Ver cdigo fuente

En este ejemplo establecemos dimensiones, unidades de medida y orientacin del documento. Comprobaremos que podemos cambiar la orientacin (de normal a apaisada o viceversa) de cada una las pginas del documento.

<?php # incluimos todos los ficheros requeridos # tal como lo hemos recogido en el fichero tcpdf.inc.php # creado tal como se indica al margen include("tcpdf.inc.php"); /* vamos a configurar el documento como apaisado (P), utilizando las pulgadas como unidad de medida y unas dimensiones "no estandar" de 10 x 20 pulgadas */ # creamos un array con las dimensiones (ancho y alto); $dimensiones=array (10,20); # creamos un nuevo objeto (MiPDF) utilizando la clase FPDF

# incluyendo en este caso los valores a utilizar por el constructor $MiPDF=new TCPDF('P','in',$dimensiones); # creamos una pgina en blanco con las indicaciones del constructor $MiPDF->Addpage(); #Incluimos una segunda pgina cambiando la orientacin # un cambio de orientacin respecto a la inicial $MiPDF->Addpage('L'); # creamos una segunda pgina en blanco # en la que, al no incluir el parmetro de orientacin # utilizar el valor utilizado en la anterior $MiPDF->Addpage(); # visualizamos el documento $MiPDF->Output(); ?>
ejemplo325.php

Otros mtodos de la clase TCPDF


Aunque no tienen excesiva utilidad prctica, vamos a comentar someramente aqu -tambin los incluimos en el ejemploalgunos de los mtodos, de carcter bsicamente informativo, que incluye la clase FPDF. SetAuthor("nombre del autor"). Permite incluir una cadena con el nombre del autor. SetCreator("nombre de la aplicacin"). Permite incluir una cadena con el nombre del programa utilizado para crear el documento. SetTitle("ttulo del documento"). Permite incluir una cadena con el ttulo del documento. SetKeywords("palabras clave"). Permite incluir una cadena con una lista de palabras clave separadas por espacios. SetSubject(tema) Permite incluir una cadena de texto explicativa de los temas tratados en el contenido del documento Los datos incluidos en el documento mediante los mtodos anteriores no son presentados diractamente en el documento. Slo son visualizables cuando se exploran los metadatos del documento.

<?php # incluimos la clase fpdf que est en este mismo directorio include("tcpdf.inc.php"); /* vamos a configurar el documento como apaisado (P), utilizando los milmetros como unidad de medida y unas dimensiones "no estandar" de 140 x 200 milimetros */ # creamos un array con las dimensiones (ancho y alto); $dimensiones=array (140,200); # creamos un nuevo objeto (MiPDF) utilizando la clase TCPDF # incluyendo en este caso los valores a utilizar por el constructor $MiPDF=new TCPDF('P','mm',$dimensiones); #desactivamos encabezado y pie de pgina $MiPDF->setPrintHeader(false); $MiPDF->setPrintFooter(false); # el mtodo SetAuthor nos permite incluir el nombre del autor $MiPDF->SetAuthor('Pepe Prez'); # el mtodo SetCreator nos permite incluir el nombre de la # aplicacion que genera el pdf $MiPDF->SetCreator('clase TCPDF'); # el mtodo SetTitle nos permite incluir un ttulo $MiPDF->SetTitle('Pruebas del pdf'); # el mtodo SetKeywords nos permite incluir palabras claves # separadas por espacios y dentro de una misma cadena $MiPDF->SetKeywords('palabra1 palabra2'); # el mtodo SetDisplayMode nos permite incluir palabras claves # separadas por espacios y dentro de una misma cadena

$MiPDF->SetDisplayMode('fullpage','two'); # creamos una pgina en blanco. Incluimos, para esta primera pgina # un cambio de orientacin respecto a la inicial $MiPDF->Addpage('L'); # creamos una segunda pgina en blanco # en la que, al no incluir el parmetro de orientacin # utilizar el valor usado en el ltimo Addpage que ha sido L. $MiPDF->Addpage(); /* insertamos unas nuevas dimensiones */ $dimension2=array(97,234); /* las dimensiones anteriores pero invirtiendo el orden */ $dimension3=array(234,97); /* insertamos pginas con la misma orientacin pero utilizando cada uno de los dos arrays anteriores. Veremos que las pginas que se visualizan tienen igual tamao y orientacin. Es decir, no importa el orden en que incluyamos las dimensiones ya que ser la orientacin establecida la situe esas medidas */ $MiPDF->Addpage('L',$dimension2); $MiPDF->Addpage('L',$dimension3); # visualizamos el documento $MiPDF->Output('donpepito.pdf','I'); ?>
Los ejemplos siguientes son similares. La nica modificacin que contienen respecto al cdigo fuente anterior es la correspondiente al segundo parmetro (destino) del mtodo Output.
Destino="I" Destino="D" Destino="F"

Textos en PDF Fijacin de mrgenes


Algunas funciones de insercin de textos permiten colocar los mismos dentro de lo que podra llamarse caja de texto que no es otra cosa que la superficie de la pgina delimitada por los mrgenes de la misma. Por defecto, estos mrgenes miden 15 milmetros, por laizquierda y por la derecha del documento y 27 y 25 milmetros por la parte superior e inferior del mismo. As mismo, tambin por defecto, se establecen mrgenes para encabezado y pie de pgina de 5 y 10 milmetros respectivamente. Los valores de esta configuracin por defecto estn contenidos en constantes del fichero tcpdf_config.php. Si editamos este fichero y modificamos los valores asignado mediante la funcin define a las constantes cuyo nombre comienza por PDF_MARGIN_ (seguido de left,top, etctera) podremos adecuar a nuestras necesidades los valores de esos parmetros. Tambin podemos hacer esas modificaciones (nicamente para el documento actual) por medio del mtodo siguiente: $objeto->SetMargins(izquierdo,superior,derecho )

dnde los parmetros izquierdo, superior y derecho son los valores numricos que permiten establecer, por este orden y en la unidad de medida que se indique en el constructor, los mrgenes del documento. Si se omite el tercer parmetro (derecho) se le asignar el valor que se haya indicado para el izquierdo. Cuando se trata de establecer mrgenes entre textos y bordes de celdas contenedoras (lo veremos en los mtodos Cell y Multicell) puede utilizarse el mtodo: $objeto->SetCellPaddings( izquierda, superior, derecha, inferior)

donde izquierda, superior, derecha e inferior son, por este orden, las distancias entre texto y borde de la celda contenedora.

Si lo que pretendemos es establecer o modificar las distancias entre bordes de celdas contiguas utilizaremos el mtodo: $objeto->SetCellMargins( izquierda, superior, derecha, inferior)

donde izquierda, superior, derecha e inferior son, por este orden, las distancias entre dos celdas contiguas.

Margen inferior y salto de pgina


Por medio del mtodo: $objeto->SetAutoPageBreak( automatico, margen_inferior )

donde automatico es un valor booleano (1 0 ) que permite activar o desactivar el salto de pgina automtico. Cuando est activotrue o 1 se van aadiendo nuevas pginas, de forma automtica, hasta que se incluya la totalidad del texto especificado. En el caso de estar desactivado false o 0, los textos que excedieran los lmites de la pgina no se visualizaran, ya que no se aadira una nueva pgina. Por defecto est opcin est configurada como true. El segundo parmetro, el valor margen_inferior, permite especificar el margen inferior mnimo de la pgina. Su valor numrico deber indicarse en las unidades establecidas por el constructor. Si no se indica asumir cero con margen por defecto.

Tipo de letra, estilo, tamao y colores de texto y fondo


La eleccin del tipo de letra puede haceres mediante la funcin: $objeto->SetFont ( nombre,estilo,tamao)

donde nombre es una cadena que debe indicar el nombre del tipo de letra (helvetica, times, zapfdingbats, courier y symbol son las fuentes incluidas en la distribucin). Puedes verlas desde este enlace. El parmetro estilo puede especificarse mediante la cadena vaca ("") para el tipo normal o mediante 'B', 'I', 'U' (negrita, cursiva,subrayada) o sus combinaciones. Por ejemplo, 'BU' indicar negrita subrayada. Las fuentes de smbolos slo permiten el estilo normal. Por medio del parmetro tamao se especifica el tamao de la letra expresado en puntos. Si no se especifica otra cosa los valores por defecto son: helvetica normal de 12 puntos. $objeto->SetFontSize( numero )

Permite modificar unicamente el tamao de la fuente en uso asignndole en adelante el valor en puntos especificado en numero. $objeto->setFontSpacing ( numero )

Permite modificar en la cantidad especificada en numero la distancia entre caracteres. Por defecto su valor es 0. $objeto->setFontStretching ( numero )

Permite estrechar la fuente al porcentaje indicado en numero. Por defecto su valor es 100. $objeto->SetTextColor ( rojo,verde ,azul )

Establece el color del texto mediante los valores numricos comprendidos entre 0 y 255 representan las respectivas componentes de los colores primarios rojo, verde y azul.

$objeto->SetTextColor ( negro )

En este caso, el valor numrico negro, tambin comprendido entre 0 y 255, establece colores de la escala de grises desde el negro (cero) hasta el blanco (255). Si no se especifica un color los textos aparecern en negro. Una vez establecido un color su valor se mantiente hasta que no sea invocada nuevamente la funcin SetTextColor para su modificacin. Una forma alternativa de utilizar los colores es la de definir un color mediante el mtodo: $objeto->AddSpotColor( nombre, cyan,magenta, amarillo, negro )

permite asignar mediante una cadena cualquiera un nombre a un color (por ejemplo: micolor) y los valores cyan, magenta, amarillo ynegro son los valores porcentuales de cada una de las tintas en la composicin del color. Siempre que se les asignen nombres distintos podrn definirse cuantos colores sean necesarios. El uso de los colores anteriores para la impresin de textos requiere el mtodo: $objeto->SetTextSpotColor ( nombre, porcentaje)

donde nombre es el nombre de un color previamente creado mediante AddSpotColor y porcentaje representa el tanto por ciento de opacidad de esa tinta (100 la hara absolutamente opaca y 0 la convertira en totalmente transparente). Cuando se trata de asignar un color de fondo (fill) para textos, celdas o dibujos se utiliza una de estas opciones: $objeto->SetFillColor ( rojo, verde, azul) $objeto->SetFillColor ( negro) $objeto->SetFillSpotColor ( nombre, porcentaje )

cuyo comportamiento es idntico al descrito para el caso de colores de texto.

Posicin actual
La clase TCPDF dispone de mtodos que permiten determinar el valor actual de las coordenadas del punto de insercin (lugar donde se va a posicionar el texto, imagen o elemento grfico que se incluya) y tambin modificar el valor actual de esos puntos. Son las siguientes: $objeto->GetX() y $objeto->GetY()

permiten conocer los valores de la posiciones actuales, horizontal (X) y vertical (Y), del punto de insercin. El resultado estar expresado en las unidades establecidas por el constructor considerando como origen de coordenadas la esquina superior izquierda del documento y valores positivos horizontal y vertical los colocados a la derecha (X) y debajo (Y) del origen. Para establecer una nuevo punto de insercin se pueden usar cualquiera de estas funciones: $objeto->SetX(valor X) $objeto->SetY(valor Y) $objeto->SetXY(valor X, valor Y)

mediante las cuales estableceremos sus coordenadas: horizontal, vertical o ambas. Cuando el valor de X (en el caso SetX) es negativo se considera con referencia al margen derecho de la pgina. De igual modo, cuando se asigna un valor negativo en SetY se considera respecto a la parte inferior de la pgina.

Nmeros de pgina
La numeracin de las pginas de los documentos es factible ya que TCPDF dispone de mtodos especficos para ello. $objeto->getAliasNumPage()

Este mtodo devuelve una cadena que contiene el nmero de la pgina actual. $objeto->getAliasNbPage()()

Complementario al anterior, este mtodo devuelve el nmero total de pginas del documento.

Saltos de lnea
Mediante $objeto->Ln (medida) se ejecuta un salto de lnea. La posicin actual regresa al margen izquierdo y la vertical se desplaza en el nmero de unidades indicado en el parmetro medida.

Estilos de lnea
Cuando se trata de establecer estilos de lnea podemos recurrir a alguna de las siguientes funciones: $objeto->SetDrawColor rojo, verde, azul ) o $objeto->SetDrawColor ( negro )

permiten establecer el color de las lneas (bordes de celdas y otros elementos grficos)siguiendo el mismo criterio ya comentado para rellenos y textos. $objeto->SetDrawSpotColor ( nombre)

Igual que ocurra para textos y rellenos permite asignar a la lneas un color cuyo nombre debe haber sido definido previamente por medio de AddSpotColor. $objeto->SetLineWidth ( espesor )

Permite establece el espesor de las lneas mediante un nmero que puede un nmero decimal que debe interpretarse expresado en las unidades de medida en uso en la pgina. $objeto->SetLineStyle( $array )

Establece el estilo de una lnea segn los datos contenidos en un $array asociativo cuyos elementos son los siguientes: $array['widht']=numero Este elemento del array permite establecer el espesor de la lnea. Es una opcin alternativa a SetLineWidth $array['join']=['miter'|'round'|'bevel'] Admite uno de los tres valores indicados: miter (inglete), round (redondeado) o bevel (bisel) y establece la forma en la que se perfilarn los extremos de los trazos de las lneas discontinuas. $array['cap']=['but'|'round'|'square']. Admite uno de los tres valores indicados: but (inglete), round (redondeado) o square (cuadrado) y establece la forma en la que se dibujarn las uniones de las lneas en las esquinas del rectngulo de la celda. $array['dash']="cadena" Permite establecer el tipo de trazos que formarn la lnea. Si se indica 0 dibujar una lnea continua. Si se especificara algo como 20,10 lo que representara sera una lnea discontinua formada por trazos de color de 20 unidades de longitud seguidos de espacio en blanco de 10 unidades. Si este parmetro fuera "20,10,8,6,5,8" lo que representara sera: un trazo de 20 unidades seguido de un espacio de 10, despus ira un trazo de 8 unidades seguido de un espacio de 6 y, a continuacin, un nuevo trazo de 5 y un nuevo espacio de 8 repitindose la secuencia completa cuantas veces fuera necesario para efectuar el trazado completo.

$array['phase']= numero Permite especificar mediante un numero entero por cual de los valores indicados en dash comienza el trazado de la lnea. $array['color']=array(cyan,magenta,amarilo,negro) Permite incluir un array escalar que contenga los valores cyan, magenta,amarillo,negro que componen el color de la lnea. Esta opcin es alternativa al uso de SetDrawColor y/o SetDrawSpotColor>. En el ejemplo330 tienes algunas muestras de como definir estilos de lnea.

Inclusn de textos en el documento


El mtodo Write
La inclusin de textos multilnea puede hacerse utilizando el mtodo: $objeto-> Write ($interlinea, $texto, $enlace="", $fondo=false, $alineacion="", $nueva_linea=false)

dnde los parmetros tienen la utilidad descrita en la tabla siguiente.


Parmetro Valores Utilidad Permite establecer la interlnea del texto. Cuando se establecen valores inferiores a la separacin mnima entre renglones desoye el mandato y estable la interlnea mnima. Cadena o variable conteniendo el texto que debe incluirse mediante el mtodo Write. Es aconsejable tomar la cautela de comprobar que la codificacin del texto utiliza la misma codificacin establecida por el constructor del objeto. El texto puede extraerse de un fichero externo mediante una funcin que permita su lectura. Tal es el caso delfile_get_contents('nombre_del_fichero_externo') Permite incluir una cadena con una direccin URI. El texto se comportara como un hiperenlace Cuando este parmetro est como true el texto aparece sobre un color de fondo (puede establecerse medianteSetFillColor (negro por defecto). Establece la forma de alineacin (izquierda, centrada, derecha o justificada) del texto respecto a la caja de texto del documento. Para que los Write consecutivos cambien de alineacin hay que producir un salto de lnea. Puede hacerse mediante el parmetro $nueva_linea Cuando se establece como true el cursor se sita en la lnea a la del ltimo texto incluido. En caso contrario (false) se mantiene en la misma lnea.

$interlinea $texto $enlace $fondo $alineacion $nueva_linea

nmero cadena cadena booleano L, C, R o J booleano

ejemplo329.php

Ver cdigo fuente

Insercin de celdas con una sola lnea de texto


La forma ms simple de insercin de textos bien como elementos individuales (por ejemplo ttulos de una sola lnea) o tablas formadas por celdas que contengan una sola lnea de texto es la que utiliza el mtodo: $objeto->Cell ($ancho, $alto=0, $texto="", $borde=0, $salto_de_linea=0, $alineacion="", $fondo=false, $enlace="", $ajuste_horizontal=0, $ignore_min_height=false, $alin_vertical_texto='T', $alineacion_vertical='M')

que imprime un rea rectangular, con fondo y bordes opcionales y que puede contener una cadena de texto que puede alinearse respecto a los bordes de la celda. La esquina superior izquierda de la celda se sita en la posicin actual del punto de insercin. Despus de ser invocado este mtodo el punto de insercin puede desplazarse a la derecha o a la lnea siguiente. El texto puede ser utilizado con un hiperenlace y, adems, puede expandirse en tamao o en espaciado para ajustarse a las dimensiones de la celda. Los parmetro que utiliza esta funcin, cuyos valores por defecto puedes ver detrs del nombre de cada uno de ellos, son los que comentamos en la tabla siguiente.
Parmetro Valores Utilidad Ancho de la celda expresado unidad de medida establecida en la llamada al constructor TCPDF. Si es cero se extiende desde el punto de insercin hasta el margen derecho de la pgina

$ancho

nmero

$alto $texto

nmero cadena 0 1

Alto mnimo de la celda expresado en la unidad de medida establecida en la llamada al constructor. La altura de la celda se ajustar al texto contenido en ella. Si se estable altura cero la celda se adaptar a las dimensiones de su contenido Cadena o variable conteniendo el texto que debe incluirse mediante el mtodo Cell. Es aconsejable tomar la cautela de comprobar que la codificacin del texto utiliza la misma codificacin establecida por el constructor del objeto. La celda se visualizar sin bordes Pertime visualizar la celda con un borde del color y ancho especificados por los mtodos SetDrawColor ySetLineWidth o por las opciones poder defecto de estos (negro de 1 unidad de espesor) Esta cadena que permite, siempre que se mantenga el orden, elegir todas o varias de las letras indicadas sirve para establecer por qu parte de la de la celda se aadirn bordes. L alude a la izquierda, T a la parte superior, R a la derecha y B a la parte inferior. Por ejemplo: 'TB' dibujara bordes por la parte superior e inferior de la celda, 'LB' los pondra por la izquierda y por debajo Y 'LRB' pondra bordes por todas partes excepto por la parte inferior. Cuando no se especifica este valor o se especifica 0 (valor por defecto) se establece que el punto de insercin, despus de la llamada a este mtodo, se sita justamente en el borde derecho de la celda. Mediante esta opcin, la celda siguiente que se incluya se situar en el margen izquierdo de la pgina y debajo de la fila actual. Cuando se indica este valor, la prxima celda que se incluya aparecer debajo de la actual y alineada al borde izquierdo de esta. Establece la forma de alineacin (izquierda, centrada, derecha o justificada) del texto respecto a la celda

$borde 'LTRB' 0 $salto_de_linea 1 2 $alineacion $fondo $enlace

L, C, R o J contenedora. booleano cadena 0 1 2 3 4

Cuando este parmetro est como true la caja contenedora aparece un color de fondo (puede establecerse mediante SetFillColor (negro por defecto). Permite incluir una cadena con una direccin URI. El texto se comportara como un hiperenlace No realiza ningn ajuste del texto que puede desbordar el espacio delimitado por el recuadro contenedor Se producir, slo si es necesario un estrechamiento del texto hasta lograr que quepa en el recuadro contenedor. Reducir o expandir el ancho del texto para ajustarlo a las dimensiones del recuadro contenedor Reducir la separacin entre caracteres (sin alterar el ancho de la tipografa) si resulta necesario para que quepa el texto en el marco contenedor Aumenta o reduce la separacin entre caracteres para ajustar el texto al marco contenedor Cuando la altura asignada a la celda es demasiado pequea para contener el texto con la fuente establecida si este parmetro est como false (0) la altura de la celda se ajustar para contener el texto. Si esta opcin est configurada como true (1) se respetar la altura de la celda y el texto aparecer fuera de los bordes de esta.l El borde superior del contenedor se alinear con el valor de la ordenada especificada en el parmetro y El borde superior de las letras se alinear con el valor de la ordenada especificada en el parmetro y La lnea base de las letras se alinear con el valor de la ordenada especificada en el parmetro y El borde inferior del contenedor se alinear con el valor de la ordenada especificada en el parmetro y El texto se alinea verticalmente a la parte superior del contenedor El texto se alinea verticalmente al centro del contenedor El texto se alinea verticalmente al borde inferior del contenedor

$ajuste_horizontal

$ignore _min_ height

booleano

T A $alin_vertical_texto L B T $alineacion_vertical C B

El punto de insercin de cada una de las celdas se establece de la forma siguiente: El resultante de la ejecucin anterior de otro mtodo de la clase. Si va precedido de una llamada al mtodo AddPage se situar en el vrtice superior izquierdo de la caja de texto (despus de aplicar los mrgenes) de la pgina. Si va precedido de una llamada al mtodo Ln se situar en el margen izquierdo de esa nueva lnea. Si va precedido de SetXY se situar en los coordenadas establecidas por este mtodo. Si va precedido de una llamada anterior al mtodo Cell se situar en la posicin condicionada por el valor del parmetro Lnincluido en aquella llamada.
ejemplo330.php Ver cdigo fuente

Cuidado! Segn las prestaciones del equipo que estemos utilizando y la complejidad de PDF que tratemos de generar puede aparecernos el mensaje de error: Fatal error: Maximum execution time of 30 seconds exceeded. Esto se debe a se ha sobresado el tiempo mximo por defecto. Hay dos maneras de evitar ese error. Una de ellas sera modificar ese tiempo en fichero php.ini. La segunda sera incluir en el encabezado del script la instruccinset_time_limit(segundos) dnde segundos el nuevo lmite de ejecucin que tendr nicamente validez para el documento actual.

Transformaciones en celdas
La clase TCPDF dispone de mtodos que permiten efectuar transformaciones grficas de algunos elementos entre los que se incluyen las celdas. Toda trasformacin comienza con una llamada al mtodo $objeto->StartTransform() y acaba con $objeto>StopTransform(). La estructura del cdigo podra ser similar a esta: $objeto->StartTransform() ... ... aplicacin de las funciones de transformacin obj->Cell(....) Incluir la celda que ser abjeto de transformacin $obj->StartTransform();

Este tipo de acciones requieren los mtodos siguientes: $objeto-> Rotate (angulo,x,y)

dnde el angulo de giro se expresa en grados sexagesimales y se mide en sentido trigonomtrico y los valores de x e y son las coordenadas del centro de giro. La transformacin producir un giro de la celda respecto a su centro de giro. o $objeto-> Rotate (angulo) o o $objeto-> Rotate (angulo, "","")

cuando no se especifica el centro de giro la transformacin producir un giro de la celda respecto a su vrtice superior izquierdo. Esta funcin es equivalente a utilizar en la anterior, las coordenadas actuales del punto de insercin como centro de giro.

Cuidado! Rotate(ang,"","") y Rotate(ang,0,0) producen resultados distintos. El primero considera como centro de giro las coordenadas actuales del punto de insercin y el segundo considera que ese centro est situado en la esquina superior izquierda de la pgina.
$objeto-> Translate (x, y)

produce una translacin de la celda desde el punto de insercin actual hasta otro punto situado x unidades a su derecha (izquierda si su valor es negativo) e y unidades hacia abajo (arriba si su valor es negativo). $objeto-> SkewX (angulo, x, y)

transforma la celda (rectangular) en un paralelogramo inclinando los lados verticales del rectngulo original en la medida indicada porang (tambin en grados sexagesimales y medido en sentido trigonmetrico) siendo el centro de la tranformacin el punto de coordenadasx,y. Si se omiten estos valores consider con centro el punto de insercin actual. $objeto-> SkewX (angulo, x, y)

transforma la celda (rectangular) de modo similar al anterior aunque ahora los lados que sufren el cambio de orientacin son los horizontales. $objeto-> ScaleX (porcentaje, x, y), $objeto-> ScaleY (porcentaje, x, y) y $objeto-> ScaleXY (porcentaje, x, y)

son tres opciones que permiten transformar la celda modificando sus dimensiones horizontales, verticales ambas y sus contenidos en el porcentaje incluido como parmetro en cada una de las funciones. Las coordenas x e y corresponden al centro de la transformacin. Si se omiten se tomar como tal el punto de insercin actual. $objeto-> MirrorV (angulo, y)

transforma la celda mediante una simetra axial (como si se tratara de un espejo) cuyo eje de simetria es la recta horizontal de ordenada y. Si se omite se considerar la ordenada del punto de insercin actual $objeto-> MirrorH (angulo, x)

transforma la celda mediante una simetra axial (como si se tratara de un espejo) cuyo eje de simetria es la recta vertical de abscisax. Si se omite se considerar la ordenada del punto de insercin actual $objeto-> MirrorP (angulo,x, y)

transforma la celda mediante dos simetras axiales (como si se tratara del efecto de un espejo reflejado en otro espejo). La primera transformacin ser realiza respecto a la recta vertical de abscisa x y la segunda respecto a la horizontal de ordenada x. Si se omiten se considerar la ordenada del punto de insercin actual
ejemplo331.php Ver cdigo fuente

Celdas multilnea
La creacin de celdas sin la restriccin del mtodo anterior en cuanto al nmero de lneas es posible mediante el mtodo: $obj->Multicell ($ancho, $alto, $texto, $borde=0, $alineacion='J', $fondo=false, $salto_de_linea=1, $x='', $y='', $reseth=true, $ajuste_horizontal=0, $ishtml=false, $autopadding=true, $maxh=0, $alineacion_vertical='T', $fitcell=false)) cuyas propiedades $ancho, $alto, $texto, $borde, $alineacion, $fondo, $salto_de_linea, $ajuste_horizontal y $alineacion_vertical, coinciden con los indicados para cell en la tabla anterior, siendo los restantes los que se indican en la tabla siguiente.
Parmetro Valores Utilidad Abscisa del punto de insercin expresada en las unidad de medida establecida en la llamada al constructor TCPDF Ordenada del punto de insercin expresada en las unidad de medida establecida en la llamada al constructor TCPDF Si se establece como false la celda actual mantendr como interlnea la altura que tuviera la celda que le precede. Caso de ser true (valor por defecto, la interlnea se establecer automaticamente ajustndose al tamao de la letra en uso). La altura de la celda previa ser a estos efectos la altura real de la celda despus de haberle incluido el texto (si excede lo establecido en el parmetro $alto) o el valor de $alto en caso de no sobrepasar esa altura Si se establece true permite incluir textos en formato HTML. Esta opcin en la versin actual de la clase presenta bastantes restricciones. Si se configura como true (1) el margen interior de la celda se ajusta de manera automtica a lo establecido mediante SetCellPaddings a los cuatro bordes de la celda. Si su valor es false(0) ese ajuste de espacios se realiza nicamente respecto a los bordes izquierdo y derecho. Establece la altura mxima que puede tener la celda. Cuando se especifica, este valor debe ser mayor o igual que parmetro h y su valor mximo puede permitir que la celda sobrepase el margen inferior de la pgina. Cuando se especifica cero se desactiva la opcin. Requiere que el parametro ishtml est configurado como false Si se configura como true el tamao de la fuente puede ser reducido hasta adaptarse a las dimensiones de la celda contenedora. Requiere que est definido $maxh con un valor distinto de cero

$x $y $reseth $ishtml

nmero nmero Booleano Booleano

$autopadding Booleano $maxh $fitcell nmero Booleano

Sigue los mismos criter