Documentos de Académico
Documentos de Profesional
Documentos de Cultura
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.
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.
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)
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
rhino.acme.com x.acme.com
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
rhino.acme.com x.acme.com
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
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.
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.
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.
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:
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:
219
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.
384
(lnea en blanco)
cambiar por:
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
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
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.
php5ts.dll
Directorio
libeay32.dll
ssleay32.dll
\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 ="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 = 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:
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.
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.
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.
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.
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.
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.
config.default.php config.inc.php
Cambios Donde dice:
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;
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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"; } ?>
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.
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.
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.
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:
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.
<?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.
18 11 8 10
9 2 3 16
22 3909821048582988049 3909821048582988048 1
3211838877954855105157369 3211838877954855105157368 1
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
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.
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.
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.
Certificados digitales
Certificado digital
Cuando recibimos informacin cifrada con clave asimtrica pueden darse varias situaciones. Entre ellas estas:
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.
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.
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.
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.
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.
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
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.
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.
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.
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 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:
120
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
<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>
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
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:
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:
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 :
<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.
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:
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 :
<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.
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
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.
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).
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.
<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.
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
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.
<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.
<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
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.
<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.
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.
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.
/* 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.
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
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.
~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
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
Cuidado! Por si existieran dudas por problemas de visualizacin tanto FILE como LINE tienen que llevar dos guiones bajosdelante y otras dos detrs.
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.
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.
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']
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']
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']
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']
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']
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']
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
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.
/* 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.
<?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
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)
31
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
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
$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
$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"
12 0
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
$a2=2147483647
$a3=-2147483647
$a4=23.7678
$a5=3.1416
$a6="347"
$a7="3.1416"
$a8="Solo literal"
0 1 integer 12
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
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.
<?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.
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> //-->
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.
que devuelve una cadena (GET POST) que especifica el mtodo de envo utilizado.
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.
<?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
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.
Operadores aritmticos
Las diferentes operaciones aritmticas se realizan en PHP utilizando la siguiente sintaxis: $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);
<?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
12 12 12
12 12 12 12 -7.3 12 -7.3 12
-7.3 -7.3 5 5 -3
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)
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
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.
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.
$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"
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)
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.
Log10($a)
Devuelve el valor del logaritmo decimal de valor numrico contenido en la variable $a Exp($a)
$a
Resultado
Logaritmo neperiano Logaritmo neperiano Logaritmo decimal Logaritmo decimal exponencial e exponencial e exponencial e
a a a
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()
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
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
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
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
10 10 10 8 16
8 16 2 10 10
2 7 5 18
10 14 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
0 2 1 1 . , '
, , . esp
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.
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
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
<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
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.
0 1 2 3 4 5 6
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.
$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
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.
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:
2 2-1
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
Piloesa 1-1
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
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
0 * 1) espacio Relleno
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
Devuelve la longitud (nmero de caracteres) de la cadena. Los espacios son considerados como un caracter ms. strtolower(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)
chop(cadena)
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 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
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
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
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.
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.
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
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.
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)
$a="<H1>A</H1>"
A
<H1>A</H1>
$a="<H1>A</H1>"
La tabla de sustituciones de htmlspecialchars es esta: Sustitye & por & " por "
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
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 >= $B
$B="123ABC" >=
$A="abc" $B="ABC" $A="abc" $B="abc" $A="abc" $B="abcd" $A="A" $A="a" $B="a" $B="A"
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
$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
$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:
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
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.
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
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
$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
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
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
El operador $A-Valor inicial de la variable Sintaxis $a=23 $a=23 echo $a--; echo $a Resultado 23 22
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
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
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; ?>
<?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)
<?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
<?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.
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.
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
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.
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
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.
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.
} 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
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.
?>
ejemplo62.php
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
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
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.
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++):?> <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.
Lectura de valores
Utilizando la sintaxis:
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
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
<?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 ; }
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
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
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
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
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
subpatrones que numerados de izquierda a derecha resultarn identificados por \\2 y \\3 (verde y azul respectivamente)
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
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]*
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
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.
El parmetro $coincidencias es opcional. Cuando se incluye recoger en un array con ese nombre los resultados de la bsqueda.
<?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
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.
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
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.
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)
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
<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>";
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.
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.
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.
"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
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.
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.
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.
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
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 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
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
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>"; }
# 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
$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.
<?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
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
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
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("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
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
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
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
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
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.
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.
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
Tammuz Messidor
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.
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 ... ...... }
<?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
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.
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
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.
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
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.
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.
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.
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)
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)
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 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
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.
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
# 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
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
<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>";
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.
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.
<?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>"; } ?>
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.
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)
gzrewind($f)
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 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.
<?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
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)
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.
<?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
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.
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.
<? # 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
<?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
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)
<?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
ftp_cdup($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.
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.
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
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).
Cambia el nombre del fichero nombre_actual por el indicado en la cadena nuevo_nombre. ftp_delete($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.
<?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.
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"; } ?>
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.
<? #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()); ?>
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.
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.
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.
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.
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"; } ?>
# 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"; } ?>
.= "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;";
/* 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)); */
/*
$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.
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.
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
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.
Si se tratara de una imagen en formato PNG (recuerda que debe estar definido en Header) la sintaxis sera: Imagepng($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.
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 */
<?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
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
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
<?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
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
<?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); ?>
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.
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.
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
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
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
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.
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.
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!
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
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.
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); ?>
<?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
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); ?>
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.
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.
/* 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
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
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
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
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
Aplicar
0 1 2 3
Brillo=60 Contraste=10 Rojo=10 Verde=10
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
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
Pixelacin avanzada Si
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.
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
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
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
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);
$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
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.
Deformacin vertical
Deformacin horizontal
Detectar bordes
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:
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
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
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
<?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
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.
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.
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:
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.
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 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
<?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
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.
<? 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.
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>";
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
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
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
<?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>"); } ?>
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)...
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.
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.
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.
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
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.
Como es obvio, adems de tener en marcha el servidor Apache en modo local es preciso que nuestro equipo disponga de acceso a Internet.
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.
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.
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
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
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)
<?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 */
"<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
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++){
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
<?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
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.
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.
<?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.
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 */ ................ ................ }
<?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
......... }
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
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.
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:
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
<?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"
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.
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.
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 )
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.
ejemplo329.php
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
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
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
Sigue los mismos criterios indicados para Cell en lo relativo al posicionamiento del punto de insercin cuando se hace una llamada a este mtodo y permite todas las transformaciones comentadas anteriormente.
ejemplo332.php Ver cdigo fuente
Veremos ahora un ejemplo de como crear un documento a partir de un fichero de texto. En el primer ejemplo se utiliza el mtodo Writemientras que en el segundo utilizamos Multicell aplicado un padding para modificar la esttica de la presentacin
ejemplo333.php Ver cdigo fuente ejemplo334.php Ver cdigo fuente
Para que los resultados sean correctos es muy importante que el cdigo HTML est limpio y bien formado. De lo contrario los resultados pueden resultar muy diferentes a los deseados. Los parmetros $fondo, $reseth y $alineacion coinciden con lo descrito en funciones anteriores. Los restantes son estos:
Parmetro Valores Utilidad Es el texto a incluir en el documento junto con sus etiquetas HTML. Si se establece como true agrega un salto de lnea al final del texto. Si es cierto agrega el contenido en una celda a la derecha de lo anterior
ejemplo335.php
Textos multicolumna
La clase TCPDF dispone de dos mtodos que permiten incluir, utilizando el mtodo Write, textos varias columnas. Para ello es preciso establecer en nmero de columnas deseado utilizando la funcin: $objeto->setEqualColumns(columnas, ancho)
mediante la cual se puede establecer el nmero de columnas deseadas y el ancho de las mismas. La funcin determinar de forma automtica el espacio entre columnas a partir del ancho de la pgina (deducidos los mrgenes izquierdo y derecho) y del nmero y ancho de las columnas. Si el ancho se estableciera de tal forma que no hubiera espacio entre columnas la propia funcin restringira ese ancho a un valor mximo que permita un margen mnimo entre columnas. Si no se especifican los parmetros columnas y ancho ser considerada una sola columna cuyo ancho sera igual al espacio entre los mrgenes izquierdo y derecho de la pgina. Una vez definido el nmero y ancho de las columnas y antes de incluir textos ser preciso situar el punto de insercin en la columna adecuada. Para ello la clase dispone del mtodo siguiente: $objeto->selectColumn(columna)
Cuando no se incluye el parmetro columna se interpreta la primera columna de la izquierda de la pgina. Una vez ejecutadas estas dos funciones solo faltara insertar el texto mediante la funcin Write tal como puede verse en los ejemplos siguientes.
ejemplo336.php
ejemplo337.php
Este mtodo debe incluirse antes de empezar a escribir nada en las pginas y requiere que se hayan definido los espaciones en blanco mediante el array_de_regiones que es un array bidimensional de esta forma: $array_de_definiciones=Array(); $array_de_regiones[ ]=array('page' =>"pagina", 'xt' =>num, 'yt' =>num, 'xb' =>num, 'yb' =>num, 'side' =>"L")
donde page recoge en una cadena el nmero de la pgina en la que pretendemos reservar el espacio; side, que puede tomar los valores "L"(izquierda) o "R" (derecha), especifica si la reserva del espacio que pretendemos se har en el margen izquierdo o derecho de la pgina. Los parmetros xt, yt, xb e yb corresponden a las coordenadas de los puntos sealados en la imagen. Si establecemos xt y xb con el mismo valor el rea reservada se trasnsformar en un rectngulo. Podremos establecer y combinar las reas que deseemos tal como puedes ver en el ejemplo.
ejemplo338.php Ver cdigo fuente
donde x0, y0, x1 e y1 son la coordenadas de los extremos del segmento y donde $estilo_segmento es un array que incluye los valores requeridos por el mtodo SetLineStyle. Si no se especifica este valor la lnea utilizar el estilo por defecto o el ltimo que haya sido definido en el script. En este ejemplo, adems de aplicar el dibujo de segmentos, procuraremos ver las diferentes opciones de definicin y modificacin de los estilos tal como hemos sealado en la pgina anterior al referirnos a los bordes de las celdas.
ejemplo339.php Ver cdigo fuente
Lneas poligonales
El dibujo de lneas poligonales puede hacerse mediante el mtodo: $objeto->Polyline ( poligonal, tipo_de_trazado, estilo*, color_fondo )
donde poligonal es un array que contiene las coordenadas de los puntos de la misma. El parmetro tipo_de_trazado es uno de los valores que comentamos en la tabla de siguiente y que permiten establecer eventuales rellenos, bordes y cierres en la poligonal.
Valor Utilidad Traza la lnea sin cerrar la poligonal Cierra la poligonal (agregando un segmento que une el primer punto y el ltimo) y dibuja la lnea Rellena el trazado sin dibujar la lnea. Utiliza la regla del nmero distinto (nonzero winding number) para determinar la regin a rellenar. Rellena el trazado sin dibujar la lnea. Utiliza la regla del par - impar (even-odd) para determinar la regin a rellenar. Traza la lnea (sin cerrarla) y rellena el trazado usando lla regla del nmero distinto (nonzero winding number) para determinar la regin a rellenar Traza la lnea (sin cerrarla) y rellena el trazado, usando la regla del par - impar (even-odd) para determinar la regin a rellenar. Cierra el trazado, dibuja la lnea y rellena usando lla regla del nmero distinto (nonzero winding number) Cierra el trazado, dibuja la lnea y rellena usando la regla par-impar (even-odd) para determinar la regin a rellenar Esta opcin permite utilizar elementos grficos cerrados (rectngulos, circulos, etctera) para recortar imgenes.
Mediante el array estilo* puede definirse el modo de trazar la polilnea que puede aplicar un estilo_segmento distinto para cada uno de los segmentos que componen la poligonal. Si no se establece aplicar a todos los segmentos el ltimo de los definidos en el documento. El array estilo* puede tener una de estas formas: $estilo=array ( 'all'=>estilo_segmento) aplicar el estilo_segmento a todos los segmentos del trazado. Recuerda que lo hemos comentado en la pgina anterior al referirnos al mtodo SetLineStyle y podra tener una forma similar a esta: $estilo_segmento =array('width' => 0.5,'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(255, 0, 255)) $estilo=array ( estilo_segmento1, estilo_segmento2, ...) ira aplicando los sucesivos estilos incluidos en el array a cada uno de los segmentos que conforman la polnea. Si el nmero de segmentos fuera mayor que el nmero de elementos del array de estilos aplicar a los no indicados el ltimo de los indicados en el array. Si el array de estilos contuviera valores igual a cero se entendera que los segmentos afectados no seran trazados.
Para el caso de trazados cerrados y con un color_de_fondo podremos especificar como cuarto parmetro del mtodo un array que contenga los valores RGB del color de fondo aplicable.
ejemplo340.php Ver cdigo fuente
Curvas de Bezier
Mediante el mtodo: $objeto->Curve(x0, y0, x1, y1, x2, y2, x3, y0, tipo_de_trazado, estilo_segmento, color_fondo)
dnde x0 e y0 son las coordenadas del punto inicial, x3 e y3 las del punto final los puntos x1, y1, x2 e y2 son las respectivas coordenadas de los puntos de control (manejadores de las curvas de Bezier) de los puntos inicial o final se consigue dibujar una porcin de curva entre ambos extemos. En la imagen pueden verse con ms detalle la posicin de los puntos. El resto de los valores, tipo_de_trazado,estilo_segmento y color_de_fondo son exactamente los mismos definidos anteriormente para el caso de las polilneas.
Las curvas obtenidas mediante este mtodo son susceptibles de ser modificadas utilizando la funciones de transformacin que hemos comentado en la pgina anterior.
ejemplo341.php Ver cdigo fuente
Dibuja un rectngulo cuyo vrtice superior izquierdo est situado en el punto sealado por las coordenadas x e y con dimensionesancho y alto. Los parmetros tipo_de_trazado y color_fondo son los mismos sealados para curvas y poligonales y , estilo* define el estilo de cada uno de los lados mediante array asociativo que puede tener la forma array('all'=>estilo_segmento) si se trata de aplicar un estilo nico a los cuatro lados. Si pretendemos que cada lado tenga un estilo diferente debemos utilizar una forma del tipo: array('L'=>estilo_izquierda, 'R'=>estilo_derecha,'T'=>estilo_superior,'B'=>estilo_inferior) donde los diferentes estilos incluidos como valores de los elementos del array asociativo son a su vez arrays que definen los estilo_segmento respectivos. Cuando se incluye un cero como valor de una o varias de las posiciones estas no sern dibujadas. $objeto->Circle(x, y, radio, inicio,final, tipo_de_trazado, estilo_segmento, color_fondo ) Dubuja un crculo con las lneas y rellenos indicados en los parmetros tipo_de_trazado, estilo_segmento y color_fondo con su centro situado en el punto de coordenadas x e y y con el radio especificado. Si se especifican valores para inicio y final (sus valores por defecto son 0 y 360) se representara nicamente el sector circular delimitado por los radios que forman angulos inicio y inicio con el eje horizontal. $objeto->Ellipse(x, y, semieje_horizontal, semieje_vertical, inclinacion, inicio, final, tipo_de_trazado, estilo_segmento, color_fondo)
Dibuja una elipse (o una porcin de ella) siguiendo idnticos criterios a los indicados para el crculo. La nica diferencia en cuanto a parmetros es que se incluyen semieje_horizontal y semieje_vertical (medida de los semiejes de la elipse) e inclinacion que indica el angulo que forma con la horizontal el eje de la elipse. $objeto->RoundedRect(x,y,ancho,alto,radio_esquina,forma_esquinas,tipo_de_trazado, estilo_segmento, color_fondo ) Dibuja un rectngulo del ancho y alto especificados con sus esquinas redondeadas y con un radio_esquina, cuyo vrtice superior izquierdo viene especificados por los valores de x e y. El parmetro forma_esquinas es una cadena del tipo "1011" que indica cuales de las esquinas (las sealadas con 1) han de ser redondeas y cuales no (las marcadas con 0). El primer valor corresponde a la esquina superior derecha continuando por las siguientes en el sentido de avance de las agujas del reloj. Los parmetros tipo_de_trazado, estilo_segmento,color_fondo son los mismos comentados anteriormente. El rectngulo redondeado debe utilizar el mismo estilo de lnea para todo su contorno y tanto los rectngulos de todo tipo como los crculos, elipse y tambin los polgonos soportan las funciones de transformacin que hemos comentado en la pgina anterior.
ejemplo342.php
dnde Xc e Yc son las coordenadas del centro de la circunferencia circunscrita, radio es el radio, lados el nmero de lados,angulo_inicial el ngulo (medido en sentido trigonmetrico) que forma con la parte negativa del eje vertical el radio correspondiente al primer vrtice del polgono, circunferencia es un valor booleano que indica si debe representarse o no la circunferencia circunscrita, tipo_de_trazadolas opciones de relleno y trazado del polgono siguiendo el criterio de la tabla ya comentada en mtodos anteriores, estilo* un array especificando los estilos de lnea del polgono (igual que ocurra con las poligonales puede aplicarse un estilo distinto a cada uno de los lados), color_fondo el color de relleno del polgono, siendo tipo_circunferencia, estilo_circunferencia y relleno_circulo los parmetros ya conocidos aplicados esta vez a la circunferencia circunscrita en el caso de que sea representada.
Polgonos estrellados
Cuando se trata de polgonos estrellados puede utilizarse el mtodo: $objeto->StarPolygon(Xc, Yc, radio, lados, ng, angulo_inicial, circunferencia, tipo_de_trazado, estilo*, color_fondo , tipo_circunferencia, estilo_circunferencia, relleno_circulo)
cuyos parmetros coinciden exactamente con los descritos para el caso del polgono regular con la nica salvedad de que aade uno nuevo, ng, cuya funcionalidad puede verse en esta imagen.
El mtodo StarPolygon lo que hace es determinar las posiciones de los vrtices de un polgono regular y trazar una poligonal cerrada(el trazado acaba al llegar al punto de partida) formada por las diagonales que unen dos vrtices separados ng posiciones. Obviamente cuando el valor de ng es 1 los vrtices a unir sern consecutivos y por lo tanto dibujar un polgono regular.
ejemplo343.php Ver cdigo fuente
Imgenes
Insertar imgenes
La integracin de imgenes en un documento PDF puede hacerse mediante el mtodo: $objeto->Image ( imagen, x, y, ancho, alto, tipo, enlace, punto_insercion, remuestreo, resolucion, alineacion, imk, imgk, borde, proporcionalidad, ocultar, encajar)
dnde: imagen es la ruta y nombre de la imagen, x e y las coordenadas donde se posicionar la esquina superior izquierda de la misma, ancho y alto sus dimensiones despus de ser insertada en el documento. Si se omitiera una de las dos dimensiones (o se asignara el valor cero) redimensionaria a la medida especificada manteniendo la otra un valor proporcional a sus dimensiones originales. Si especificamos ambos valores iguales a cero el resultado depender del valor que asignemos al parmetro booleano encajar. Si ese valor fuera false la imagen se incluira segn sus dimensiones originales y si su altura fuera mayor que el espacio disponible en la pgina actual producira un salto de pgina de forma automtica. Cuando encajar tuviera el valor true la imagen se redimensionara manteniendo la proporcionalidad y limitando su tamao de forma que no sobrepase los mrgenes del documento. Mediante el parmetro tipo se puede especificar el tipo de imagen que puede ser, entre otros: GIF, JPG, PNG BMP. Si no se especifica lo tomar de la extensin de fichero que contiene la imagen. El parmetro enlace permite incluir una cadena conteniendo el destino de un eventual hiperenlace. Mediante la propiedad punto_insercion se puede especificar la posicin en la que quedar el punto de insercin despus de haber incluido la imagen. Admite uno de estos valores: T (arriba a la derecha de la imagen), M (en el centro a la derecha de la imagen), B (en la parte inferior de la imagen a la derecha de la misma) o N (en una nueva lnea debajo de la imagen). El parmetro remuestreo es un valor booleano que est ntimamente relacionado con resolucion que es el que le sigue en la llamada al mtodo. Cuando remuestreo toma el valor false la imagen no ser remuestreada y mantendr su resolucin original. Cuando se le asigna el valor true o 1 remuestrear la imagen para ajustarla a la resolucin especificada en resolucion siempre que el valor de esta (expresada enpuntos por pulgada) sea superior al de la imagen original. En el caso de que remuestreo tuviera valor 2 el proceso se efectuara tanto si aumente como si disminuye la resolucin original. La visualizacin en pantalla no se afecta por estos parmetros sin embargo si puede tener gran importancia a la hora de producir un documento impreso. En esos casos lo aconsejable ser ajustar la resolucin de la imagen al valor que vaya a ser utilizado por la impresora. Mediante el parmetro alineacion es posible alinear una imagen dentro de la lnea en la se encuentre el punto de insercin. Admite como valores L, C o R dependiendo si pretendemos alinear a la izquierda, centro o derecha del documento. El parmetro imk parece estar obsoleto y se refieren a la creacin de reas de transparencia en imgenes. Tienen bastantes restricciones de uso y es absolutamente prescindible. Bastara con utilizar imgenes en formato PNG GIF que permiten directamente esas transparencias. Por el contrario, la opcin imgk si tiene gran utilidad cuando se trata de recortar imgenes siguiendo el borde de una figura cerrada tal como veremos cuando comentemos el proceso de este tipo de transformaciones.
Cuidado! Cuando al invocar el mtodo Image sea necesario incluir las opciones imk, imgk utiliza siempre false como valores. Hemos comprobado que si ponemos una cadena vacia '' (aparentemente podra parecer los mismo) aparecen mensajes de error en la visualizacin con algunas imgenes.
El parmetro borde permite asignarle un borde a la imagen. Los valores posibles son: 0 (sin bordes); 1 (borde por defecto) o un array idntico al descrito para el caso de los rectngulos que permite configurar las caractersticas especficas de los bordes de cada uno de los lados de la imagen. Cuando el valor de proporcionalidad es false la imagen se acomodara a las dimensiones especificadas en ancho y alto provocando distorsiones en la misma. Por el contrario, cuando su valor no es false la imagen se acomoda a la caja manteniendo la proporcionalidad. Como consecuencia de ello pueden quedar espacios sobrantes que podran distribuirse a nuestra voluntad dependiendo del valor que asignemos a proporcionalidad. Ese parmetro es una cadena formada por dos caracteres de los cuales el primero ha de ser L (izquierda), C(centro) R (derecha), mientras que para el segundo se requiere T (arriba), M (en medio) B (abajo). Dependiendo de esta configuracin la imagen se acomodar de una u otra forma al marco delimitado por los parmetros ancho y alto. Por ltimo, valor booleano ocultar establece la no visualizacin de la imagen en caso de asignarle el valor true. Cuando su valor esfalse (valor por defecto) la imagen se visualiza normalmente. En el ejemplo siguiente hemos desarrollado y comentado ejemplos con imgenes que utilizan las diferentes opciones aqu comentadas.
ejemplo344.php
Recortar imgenes
Una de las posibilidades grficas de la clase TCPDF es la de recortar imgenes siguiendo el permetro de una figura cerrada. El procedimiento para ello es el siguiente: $objeto->StartTransform() Empezamos que invocar el mtodo que inicia una transformacin. $objeto->Rect(x,y,ancho,alto,'CNZ') Invocamos el mtodo que permita hacer un trazado cerrado (Circle, Elipse, Rect, RoundedRect, Polygon, StarPolygon) estableciendo como tipo_de_trazado el valor CNZ. $objeto->Image(imagen, x, y, ancho, alto, tipo) Insertamos la imagen de modo que por su posicin y dimensiones se superponga con la figura cerrada incluida en el mtodo anterior. $objeto->StopTransform() Finalizamos la transformacin. Como resultado del proceso solo se visualizar la parte de la imagen situada dentro del contorno de la figura cerrada que hace funcin de mscara. Si la figura tiene definidas bordes estos aparecern delimitando la imagen. Tambin es posible efectuar recordes de imgenes delimitndolas por los bordes de las letras que componen un texto. El proceso es bastante similar al anterior. Comienza como aquel con: $objeto->StartTransform(). A continuacin hay que utilizar este nuevo mtodo: $objeto->setTextRenderingMode(borde, relleno, recorte)
dnde borde es un valor numrico que indica el espesor de la lnea que dibuje el borde de las letras. Si se especifica cero no se visualizarn esos bordes. La opcin relleno es un valor booleano que permite especificar si la letra aparecer rellena en color negro o no. Por ltimo el paramtro recorte, tambin booleano, ha de configurarse con valor true para que permita recortar la imagen. Despus de aplicar el mtodo anterior hemos de escribir el texto. Para hacerlo utilizaremos el mtodo Write de una forma similar a esta: $objeto->Write(interlinea, texto)
El paso siguiente sera insertar la imagen con la posicin y dimensiones que permitan que texto e imagen se superpongan. $objeto->Image(imagenb, x, y, ancho, alto, tipo)
Por ltimo, tendramos que incluir el final de la transformacin mediante el ya conocido: $objeto->StopTransform() En este ejemplo pueden verse la diferentes posibilidades de utilizar elementos grficos como rutas para el recorte de imgenes tal como acabamos de describir.
ejemplo345.php Ver cdigo fuente
en el que opacidad es un valor comprendido entre 0 y 1 que indica el grado de opacidad de la imagen o texto. Por defecto su valor es 1 (opacidad total). El segundo parmetro de la funcin, modo (permite uno de los valores descritos aqu debajo) se comporta de forma muy similar a la utilizada por los programas de retoque fotogrfico en la forma de combinar elementos grficos superpuestos (imgenes, textos, trazados).
Normal: No hay interaccion entre las imgenes superpuestas. El resultado ser la consecuencia del grado de opacidad de cada una de ellas. Multiply: El valor de los pxeles de la imagen de fondo se multiplica por el valor de los pxeles de la capa superpuesta y el resultado se divide entre 255. Generalmente se obtiene un oscurecimiento de la imagen. Screen: Realiza el efecto contrario a Multiplicar (usa el inverso de todos los valores para realizar la operacin) por lo que obtenemos una imagen mucho ms clara que la original. Overlay: Los colores brillantes de la imagen de fondo se dividen entre los de la capa superpuesta mientras que los colores oscuros se multiplican. El resultado ser una superposicin de los colores de ambas capas, conservndose las luces y las sombras de la imagen de fondo. Darken: Producir una imagen ms oscura como resultado de la comparacin que realiza el programa entre los pxeles de cada imagen, mostrando los ms oscuros de cada una. Lighten: Se comporta de forma idntica a la anterior pero ahora mostrando los colores ms claros de cada imagen. Color Dodge: Este efecto es similar al que se producira si en fotografa tradicional disemos un tiempo de exposicin prologando a la fotografa. Color Burn: Produce un efecto similar a la subexposicin de la fotografa tradicional Soft Light: Produce un efecto similar a iluminar la imagen con un foco de luz difusa y suave. Hard Light: Igual que el anterior pero iluminando con una luz ms dura. Difference: Rellena parte de la imagen inferior con partes de la superpuesta. Generalmente se sustraer color de la capa con el color ms brillante en el punto que se examine Exclusion: Produce efectos similares que Diferencia pero con un contraste menor. Hue: Mezcla el valor de Tono de la imagen con el de saturacin y brillo de la imagen inferior. Saturation: Mezcla el valor de saturacin del color de la imagen superpuesta con los valores de brillo y tono de la imagen de fondo. Color: Mezcla el valor de saturacin de color de la imagen superpuesta con el valor de brillo de la imagen inferior. Luminosity: Produce el efecto inverso que Color. Mezcla los valores de saturacin y tono de la imagen inferior con el valor de brillo de la imagen superpuesta.
ejemplo346.php
han de estar configuradas como true (su opcin por defecto) para permitir que se visualicen los encabezados y pies de pgina. $objeto->setHeaderMargin(numero)
debe tener asignado un valor numrico (la distancia del borde superior de la pgina al punto donde empezar la insercin de los elementos del encabezado). Caso de no establecerlo tomara valor cero y el encabezado se situara con margen cero (a sangre) respecto al borde superior del papel. $objeto->setFooterMargin(numero)
debera estar establecido ya que con su valor por defecto (cero) empezara a escribir el pie de pgina debajo de borde inferior del papel. El nmero positivo que incluyamos en este mtodo establecer a que distancia del borde inferior empieza a presentarse el pie de pgina.
$objeto->setHeaderFont(array(nombre,estilo,tamao))
permite establecer como elementos del array escalar: el nombre de letra nombre ('times', por ejemplo), el estilo estilo (podra ser algo como 'I' italic) y el tamao tamao expresado en las mismas unidades con que se definen las dimensiones de la pgina. $objeto->setFooterFont(array(nombre,estilo,tamao))
Se comporta exactamente igual que el anterior solo que en este caso se establece la tipografa para los pies de pgina. $obj->setHeaderData(logo, ancho, titulo, subtitulo)
Mediante este mtodo podremos indicar el nombre de una imagen (logo), el ancho que pretendemos que ocupe esa imagen ancho, una cadena de texto titulo que ser el ttulo del encabezado y subtitulo una lnea de texto que ira debajo de la anterior. El pie de pgina se incluye de forma automtica y estar formado nmero de la pgina y el nmero total de pginas del documento separadas por una barra. En ambos casos se dibujara una raya horizontal delimitadora del encabezado y pie de pgina que ocupa todo el espacio entre mrgenes. Los pies de pgina se alinearan al margen derecho y los encabezados al margen izquierdo.
ejemplo347.php Ver cdigo fuente
Cuidado! Salvo que hagamos una modificacin en el fichero de configuracin (o hagamos cambios en el fichero tcpdf.php que contiene la clase), la imagen que incluyamos en el encabezado deber estar en /images/ dentro del directorio tcpdf. Para alterar esa ruta sera necesario modificar el fichero de configuracin.
<?php /*incluimos el fichero con las rutas y los include de las clases necesarias tal como venimos haciendo el los ejemplos anteriores */ include("tcpdf.inc.php"); /* empezaremos creando una clase extendida de TCPDF que permitir reescribir las funciones Header y Footer incluidas en el constructor de la clase TCPDF. Estas nuevas funciones sustituiran a las preexistentes */ class ConPies extends TCPDF { public function Header() { /*ponemos color al texto y a las lineas */ $this->SetTextColor(0,0,200); $this->SetDrawColor(255,0,0); /* definimos variables con titulo y subtitulo */ $titulo="Adios cordera"; $subtitulo="Leopoldo Alas (Clarin)"; /* posicionamos el puto de insercion 2mm. debajo del borde del papel */
$this->SetY(2); /* escribimos el titulo con la fuente que se establezca por el mtodo opcion SetHeaderFont */ $this->Cell(0, 5,$titulo,0,1,'C'); /* modificamos tipografia para el subtitulo e insertamos este */ $this->SetFont('helvetica', 'I', 7); $this->Cell(0, 2,$subtitulo,0,1,'C'); /* trazamos un rectangulo sombreado que por sus dimensiones ocupar el area de texto de la pagina */ $this->Rect(15,15,180,267,'F','',array(240,240,240)); /*trazamos una linea roja debajo del encabezado */ $this->Line(15,15,195,15); /* insertamos una imagen de fondo con 15% de opacidad */ $this->SetAlpha(0.15,'Normal'); $this->Image('./images/cordera2.jpg',55,84,100,104, '','','N','','','C'); /* recuperamos la opacidad por defecto */ $this->SetAlpha(1,'Normal'); } public function Footer() { /* establecemos el color del texto */ $this->SetTextColor(0,0,200); /* insertamos numero de pagina y total de paginas*/ $this->Cell(0, 10, 'Pagina '.$this->getAliasNumPage(). ' de un total de '. $this-> getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M'); $this->SetDrawColor(255,0,0); /* dibujamos una linea roja delimitadora del pie de pgina */ $this->Line(15,282,195,282); } } /* creamos un nuevo objeto usando la clase extendida ConPies */ $MiPDF = new ConPies(); /* definimos margenes de encanbezado y pie de pagina, tipos de letra para encabezados y piel */ $MiPDF->setHeaderMargin(2); $MiPDF->setFooterMargin(15); $MiPDF->setHeaderFont(Array('times', '', 14)); $MiPDF->setFooterFont(Array('helvetica', 'I', 10)); /* fijamos el modo de visualizacion, agregamos dos paginas y visualizamos el resultado */ $MiPDF->SetDisplayMode('fullpage'); $MiPDF->AddPage(); $MiPDF->AddPage(); $MiPDF->Output(); ?>
ejemplo348.php Ver cdigo fuente ejemplo349.php Ver cdigo fuente
Cdigos de barras
Cdigos de barras lineales
TCPDF dispone de una funcin que permite incluir cdigos de barras en los documentos PDF. El mtodo es el siguiente:
booleano numero numero numero array array booleano nombre booleano texto
'fontsize' 'label'
'cellfitalign' booleano
alineacion
Establece la posicin del punto de insercin despus de haber incluido el cdigo de barras. Admite como valores T, M, B, N que se refieren a las partes: superior derecha, centro derecha,inferior derecha o nueva lnea siempre respecto al cdigo de barras actual.
En este ejemplo pueden verse las diferentes posibilidades de este tipo de cdigos de barras.
ejemplo350.php Ver cdigo fuente
Cdigos de barras 2D
La clase TCPDF tambin permite escribir cdigos de barras del tipo 2D utilizando el mtodo: $objeto-> write2DBarcode ( codigo, tipo, x, y, ancho, alto, estilo, alineacion, distorsion )
de gran similitud al descrito anteriormente aunque con algunos elementos diferenciados en lo que se refiere a tipo, estilo y distorsion.
Este formato de cdigos admite como tipos alguno de los siguientes: RAW, RAW2, QRCODE,L, QRCODE,M, QRCODE,Q, QRCODE,H,QRCODE,L o PDF417. Por lo que respecta al estilo se define, igual que en el caso anterior, mediante un array asociativo cuyos elementos son: 'border','padding', 'hpadding', 'vpadding', 'fgcolor', 'bgcolor', 'position' con comportamientos idnticos a los descritos en el prrafo anterior y tambin'module_height' y 'module_width' que permiten establecer mediante valores numricos el alto y el ancho (expresado en puntos) de un mdulo simple. El parmetro distorsion es un valor booleano. Cuando se le asigna true puede distorsionar el cdigo de barras para encajarlo con la anchura y la altura. Si el valor es false (valor por defecto) preservar la relacin de aspecto. En el ejemplo siguiente tienes comentadas algunas de las diferentes opciones de esta funcin.
ejemplo351.php Ver cdigo fuente
Cajas de texto
Este tipo de elemento puede ser utilizado de forma que cubra las necesidades de las entradas de texto, las entradas tipo password, las reas de texto y tambin las tipo file. El mtodo que permite insertarlas es el siguiente: $objeto->TextField(nombre, ancho, alto, propiedades, anotaciones, x, y)
Valor Utilidad Es el nombre identificador del elemento que servir para asignar nombre a la variable que recoja su contenido cuando el formulario sea transferido al servidor. Son los valores del ancho y el alto del rectngulo contenedor. (**) Son las coordenadas del puntos de insercin de la esquina superior izquierda del rectngulo contenedor del rea de texto. Es un array asociativo que puede contener, entre otros, los siguientes elementos: Elemento Valor Utilidad Indica si ha de cumplimentarse obligatoriamente (true) o si no es requerido necesariamente (false). Permite asignar un valor por defecto al elemento. Si no se incluye se cargar una cadena vaca.
propiedades
'required' 'value'
booleano tpicos asteriscos de los campos tipo password. booleano defecto. numero
Cuando este valor se establece como true al teclear contenidos en el campo se visualizaran los
Permite, cuando se le asigna el valor true, impedir la modificacin de los valores asignados por Permite limitar el nmero mximo de caracteres susceptibles de ser incluidos en ese campo. Cuando este valor se configura como true permite mltiples lneas y su comportamiento es idntico al Cuando se configura como true permite seleccionar ficheros de forma similar a los formularios HTML.
booleano Requiere ser complementado con un botn (en HTML se insertan simultneamente) mediante el cual
se ejecutar la accin que permita elegir el fichero a incluir.
Permite especificar el ancho de la lnea que contornea el elemento. (*) Permite asignar un estilo al borde del elemento. Si se asigna la cadena 'solid' (valor por defecto) contornear con una lnea continua. Si se asigna 'dashed' lo har con lnea discontinua. (*) Permite establecer un color de fondo asignado mediante un array definido como array(R,G,B) dnde R, G y B son los valores de las componentes de los colores primarios. (*) Permite establecer un color de fondo asignado mediante un array definido como array(R,G,B) dnde R, G y B son los valores de las componentes de los colores primarios. (*)
'strokeColor' array
anotaciones
Permite incluir anotaciones de acuerdo con las especificaciones PDF32000_2008. Para nuestros fines no resulta necesario. Bastar que incluyamos este parmetro en forma de un array vaco: array()
(*) Este valor pueden asignados de forma global para todos los elementos del documento incuyndolo el mtodo setFormDefaultProp. (**) Si se asigna cero a los valores ancho y alto no se visualizar el campo. Si se le asignara un value podra emular perfectamente los campos ocultos (hidden) de los formularios HTML.
Botn de opcin
Este tipo de elemento puede ser utilizado de forma idntica a la contemplada en los formularios HTML. El mtodo que permite insertarlo es el siguiente: $objeto->RadioButton( nombre, ancho, propiedades, anotaciones, valor, marcado, x, y)
El parmetro nombre permite identificar el elemento (y el valor de la variable al ser enviado el formulario) y ha de ser el mismo en los diferentes elementos que conforman las opciones de eleccin. Mediante ancho especificamos el ancho del botn de opcin, las propiedadesen este caso se limitan a las caractersticas grficas ya sealadas para las cajas de texto. Las anotaciones tienen una funcionalidad y comportamiento similares (tambin aqu podemos incluir un array vaco). El parmetro valor permite especificar el valor que se asignara a la variable nombre en el caso de ser seleccionada la opcin mientras que marcado es un valor booleano que en caso de estar configurado como true hara que la opcin aparezca seleccionada por defecto. Los parmetros x e y son las coordenadas del punto de insercin del elemento.
Casillas de verificacin
Tambin se comportan de forma idntica a los formularios HTML. El mtodo que permite insertarlos es el siguiente: $objeto->CheckBox(nombre, ancho, marcado, propiedades, anotaciones, valor, x, y)
Utiliza los mismos parmetros, y con idnticas funcionalidades, que el botn de opcin. Las dos nicas diferencias a tener en cuenta es que se incluyen en distinto orden y que las casillas de verificacin deben tener siempre nombres diferentes.
Cuadro de lista
Presenta un cuadro de lista desplegando las diferentes opciones que pueden ser seleccionadas. Si se configura adecuadamente pueden hacerse una seleccin mltiple. El mtodo que permite insertarlo es el siguiente: $objeto->ListBox(nombre, ancho, alto, valores, propiedades, anotaciones, x, y)
Casi todos los parmetros son los ya conocidos. Las diferencias respecto a lo comentado para el caso de cajas de texto se refieren a los valores y a las propiedades. En caso de los valores deberemos incluir un array escalar que contenga como valores las
diferentes opciones posibles de la lista. En cuanto a propiedades pueden incluirse lo elementos de ese array asociativo relativos a la configuracin grfica y, adems, un nuevo elemento: 'multipleSelection' un valor booleano que en caso de tener asignado el valor true permite seleccionar varios items de la lista (bastara marcarlos manteniendo pulsada la tecla Ctrl). Cuando se utiliza esta opcin es muy importante tener la precaucin de agregar unos corchetes al nombre del elemento. Por ejemplo:aficiones[] en vez de aficiones. De esta forma cuando los datos sean enviados al servidor PHP interpretar la variable como un array y podr extraer de ella los diferentes valores seleccionados. Si se omitieran los corchetes PHP solo recogera el ltimo de los valores seleccionados. Si en el array propiedades incluyeramos un elemento con nombre 'value' y el asignramos como valor una de las opciones ocurrira que al ser cargado el formulario aparecera seleccionada ese valor de forma automtica.
Cuadro desplegable
Este tipo de elemento puede ser utilizado de forma idntica a la contemplada en los formularios HTML. El mtodo que permite insertarlo es el siguiente: $objeto->ComboBox(nombre, ancho, alto, valores, propiedades, anotaciones, x, y)
Se comporta de forma muy similar a la descrita en el elemento anterior. Como es lgico no permite la propiedad multipleSelection. De igual forma que ocurra en aquel caso si se incluye la propiedad value aparecer seleccionado el elemento correspondiente de la lista. Respecto al array que contiene los valores caben dos posibilidades de insercin. La primera es la ya descrita para el caso anterior:(array('valor1','valor2','valor3')). Alternativamente pueden usarse formas del tipo ( array (array ('item1','valor1'),array('item2','valor2'),array('item3','valor3') ) en la que en vez de los valores de los elementos se incluye un array de dos elementos por cada uno de ellos. El primer elemento de cada uno de esos arrays ser el texto que aparecer en el formulario y el segundo el valor que habra de asignarse al ser elegida esa opcin. Es decir, se visualizara item2 y se enviara al servidor valor2 que es el valor asociado a el.
Botones
Los botones son elementos imprescindibles en el caso del manejo de formularios. El mtodo que los incluye es este: $objeto->Button(nombre, ancho, alto, caption, accion, propiedades, anotaciones, x, y)
Los parmetros nombre, ancho, alto, propiedades, anotaciones, x e y tienen idntico significado que en casos anteriores (las propiedades se reducen a sus aspectos grficos). Incorpora como elementos nuevos el parmetro caption que ser una cadena con el texto que aparecer en el propio botn y el parmetro accion que podr incluir una llamada a una funcin de JavaScript o un array asociativo. Estos son algunos ejemplos del primer supuesto: $objeto->Button('imprime', 30, 10, 'Imprimir', 'print()', $estilo, array() , 30, 265);
insertara un botn con el estilo definido en $estilo en el que se visualizara la palabra Imprimir y que al ser pulsado ejecutarla la funcin print() del sistema del usuario. $objeto->Button('almacena', 30, 10, 'Imprimir', 'guardar()', $estilo, array() , 30, 265);
insertara un botn con el estilo definido en $estilo en el que se visualizara la palabra Guardar y que al ser pulsado ejecutarla la funcin JavaScript guardar() en el navegador del usuario. Las funciones JavaScript debe estar incluida en el propio documento pdf. Para ello la clase TCPDF dispone del mtodo: $objeto-> IncludeJS($texto_con_codigo_JavaScript)
dnde la variable $texto_con_codigo_JavaScript contiene el cdigo JavaScript que se pretende incluir en el documento. En el supuesto anterior podra ser una funcin tal como esta: function guardar(){app.execMenuItem("SaveAs");} Cuando se trata de enviar el formulario es necesario recurrir a un botn con las siguientes caractersticas: $objeto->Button('submit', ancho, alto, 'Enviar', array('S'=>'SubmitForm','F'=>'xxxxx.php','Flags'=>array('ExportFormat','IncludeNoValueFields')), $estilo, array() , x, y );
en cuyo array asociativo son obligatorios los elementos: 'S' con valor 'SubmitForm' (que har el envo del formulario); 'F' cuyo valor se la direccin del script que recoger los resultados del envo 'xxxxx.php' (equivale a action en el formulario convencional de HTML) y elemento'flags' ha de incluir un array conteniendo los valores 'ExportFormat' y 'IncludeNoValueFields'. De no hacerlo no se recibiran en el servidor los contenidos del formulario. Cuando se trata de borrar el contenido del formulario es necesario recurrir a un botn con las siguientes caractersticas: $objeto->Button('reset', ancho, alto, 'Borrar', array('S'=>'ResetForm'), $estilo, array() , x, y );
en cuyo array asociativo es obligatorio el elemento: 'S' con valor 'ResetForm' (que borrar los contenidos del formulario).
Ficheros adjuntos
El envo de ficheros adjuntos requiere el uso de tres elementos: un campo de texto, un botn y una funcin JavaScript. $objeto->TextField( 'nombre_campo',ancho,alto,array('fileSelect'=>true),array(),x,y)
el campo de texto requiere la opcin 'fileSelect'=>true $objeto->Button( 'Sube',ancho,alto,'Seleccione el archivo', "Cargar('nombre_campo')", $estilo_boton)
el botn debe incluir el la llamada una funcin JavaScript en la que debemos incluir como argumento una cadena que ha de coincidir con el el nombre_campo asignado como nombre al campo de texto. function Cargar(nombre){ var selecciona = this.getField(nombre); selecciona.browseForFileToSubmit(); } la funcion JavaScript tal como la ests viendo permite seleccionar un nombre de fichero y que de forma automtica se incluya su nombre y su ruta en el campo de texto. El comportamiento es idntico al caso de enviar ficheros desde los formularios HTML. En el cdigo fuente de este ejemplo puedes ver como hemos incluido las funciones JavaScript en una variable usando la sintaxis de documento incrustado.
ejemplo352.php Ver cdigo fuente
dnde x e y son las coordenadas del punto dnde se insertar el icono que advierte de la existencia de una anotacin. Los valoresancho y alto especifican las dimensiones de ese icono. El parmetro texto permite incluir un texto alternativo que si visualizara cuando se colocara el puntero del ratn sobre el icono. Cuando se incluye ese texto aparecer a la derecha del icono una advertencia en forma de bocadillo de cmic. Si ese texto se deja como cadena vaca no se visualizar esta ltima marca. El array que se incluir como sexto parmetro es de tipo asociativo. Su primer elemento, Subtype, tendr como valor FileAttachement(alude a la inclusin de un fichero adjunto), el elemento cuyo ndice es Name especificar en su valor el tipo de icono que se visualizar en el documento. Son vlidos los tipos: Graph, Paperclip Tag y PushPin. El elemento de ndice FS tendr como valor el nombre y la extensin del fichero que incluir en el documento. Como es lgico tal fichero ha de estar ubicado en un lugar accesible por el servidor.
Cuidado! La descarga de ficheros adjuntos (pulsando con el botn derecho del ratn sobre el icono) est restringida en Adobe Reader por razones de seguridad. Ficheros ejecutables, comprimidos, etctera no se abren en prevencin de que pudieran contener elementos maliciosos.
Cuando se trata de incluir nicamente una nota de comentario puede utilizarse el mtodo anterior con la sintaxis siguiente: $Objecto->Annotation(x, y, ancho, alto, texto, array('Subtype'=>'Text', 'Name' =>'Comment', 'T'=>titulo, 'C' => array(255, 255, 0)))
las modificaciones respecto al supuesto anterior son: la modificacin del valor del elemento Subtype que ahora toma Text como valor; la modificacin de valor del elemento Name que ahora pasa a tener como valor Comment; la inclusin del elemento T al que podremos asignar como valor el ttulo de comentario y la posibilidad de aadir un color al icono de comentario mediante el elemento C al que se asigna como valor un array cuyos tres elementos son las componentes R, G, B del color que pretende aplicarse.
dnde certificado es una cadena que comienza por file:// y va seguida de la ruta y nombre del fichero que contiene el certificado que va a ser utilizado para facilitar la comprobacin de la firma del documento; clave_privada es la clave privada del firmante (tambin debe indicarse mediante file:// y va seguida de la ruta y nombre del fichero). La contrasea ser la contrasea de uso de la clave privada. Si utilizamos el certificado de servidor mencionado en este enlace esa contrasea ser una cadena vaca ya que, tal como puedes recordar si visitas el enlace anterior, al crear la clave privada del servidor (la funcin genrsa de OpenSSL) habamos omitido el modificador -des3 precisamente para que tal contrasea no fuera requerida. Como parmetro extras vamos a utilizar una cadena vaca ya que nuestro certificados carecen de esa informacin complementaria. Como parmetro tipo podemos incluir 1 (cualquier cambio en el documento invalidar la firma), 2 (se permite la cumplimentacin de formularios sin invalidar la firma) o 3 (no invalida la firma ni la cumplimentacin de formularios ni la inclusin, modificacin o eliminacin de anotaciones).
Por ltimo, informacion es un array asociativo cuyos elementos tienen por ndices: 'Name', 'Reason' , 'Location' y 'ContactInfo' y contendrn como valores cadena conteniendo datos informativos sobre el titular del certificado digital utilizado. Esos valores podrn ser visualizados por el cliente de la forma que veremos en el prrafo siguiente. Aunque no resulta elemento imprescindible es habitual incluir en el documento algn tipo de imagen o smbolo que sugiera que el documento incluye una firma digital. Puede ser cualquier elemento grfico. Cuando se ejerce esa opcin suele complementarse con la definicin de un rea activa en el documento (normalmente la que ocupa el grfico que simboliza la firma) de modo que al pulsar con el ratn sobre esa zona se abra una ventana que facilite la informacin aludida en el prrafo anterior. En los ejemplos que incluimos a continuacin tienes una muestra del uso de anotaciones y firma digital. En el primero de ellos utilizaremos el certificado demostracin incluido con TCPDF y en el segundo haremos uso del certificado al que hemos hecho mencin encertificado de servidor mencionado en este enlace. Si no dispones de esos certificados o si la ruta no coincide el segundo de los ejemplos te dar error.
ejemplo353.php Ver cdigo fuente ejemplo354.php Ver cdigo fuente
Cuidado! En el ejemplo anterior habrs observado que en el caso de que el sistema operativo sea Ubuntu hemos aplicado la funcion realpath() a la ruta hasta el certificado y la clave privada. De no hacerlo as la ejecucin del script produce un error. La funcion realpath(ruta) devuelve el nombre de la ruta en forma de ruta absoluta cannica que tiene un valor nico y que no siempre coincide con la ruta absoluta que suele depender del sistema operativo en uso.
Tal como habrs podido observar a mirar el cdigo fuente, en este ejemplo he intentado incluir algunos fichero incrustados y a la vez crear un documento firmado con certificado digital, guardando el pdf resultante en el servidor con un nombre creado de forma aleatoria e incluyendo en el propio fichero la ruta hasta el mismo. Una vez creado el fichero se abrira de forma automtica en el navegador del cliente que podra guardarlo en su equipo y/o imprimirlo. La firma digital es facilmente comprobable en un documento digital pero es evidente que esa comprobacin es imposible en una copia impresa del documento. Al guardarlo en el servidor e incluir la direccin estaremos facilitando la posibilidad de comprobar la fidelidad de una copia a cualquiera que tenga acceso a ella.
Un ejemplo de aplicacin
Incluimos un ejemplo que intenta mostrar en alguna medida las posibilidades de esta herramienta emulando una ventanilla de registro clsica. Al ejecutar el script se carga un formulario que, una vez cumplimentado e incluidos los ficheros adjuntos solicitados, es enviado al servidor, donde se bloquean los campos del formulario y se agregan unos textos que emulan el sello de registro de entrada (en caso de identificacin mediante certificado electrnico podra incluir los datos de este). Tambin se incrustan en el documento, formando un todo con l, los ficheros adjuntos. El fichero resultante se almacena en el servidor (emulando el original para la administracin) y se devuelve al navegador una copia completa del mismo.
ejemplo355.php Ver cdigo fuente
dnde texto es una cadena que contiene el texto que aparecer en el ndice del documento, nivel ser un nmero entero que indicar a qu nivel pertenece la marca. Cero significar primer nivel (por ejemplo TEMA), uno significar segundo nivel (en el ndice colgar del de primer nivel anterior a l) y as sucesivamente. El parmetro posicion admite como valores 0 y -1. Si se especifica 1 al pulsar sobre el enlace el navegador se punto de insercin en la parte superior de la ventana contenedora del documento. Si ese valor es 0 se situar en el borde superior de la pgina que contiene el marcador.> El parmetro pagina permite especificar la pgina a la que nos redirigir el enlace. Si se incluye una cadena vaca (lo habitual) nos redirigir a la pgina que incluye el marcador actual. El parmetro estilo admite como valores 'B' (negrita), 'I' o una cadena vaca (normal) y permite especificar el estilo del texto (en ndice del documento) con que se visualizar el enlace hacia la posicin sealada por el marcador. Por ltimo el parmetro color es un array que permite indicar en modo R,G,B el color del texto de los enlaces. En este ejemplo puedes ver una muestra de las posibilidades de esta opcin.
ejemplo356.php Ver cdigo fuente
Fuentes tipogrficas
Para generar las nuevas fuentes es necesario disponer del programa pfm2afm.exe que viene incluido en el paquete tcpdf. Concretamente en el directorio /tcpdf/fonts/utils
Cuidado! En el caso de Ubuntu el proceso es idntico. Bastar con abrir el terminal, situarse en el directorio fuentes. Desde all se ejecuta el comando ttf2ufm de forma idntica a la descrita para MS-DOS.
donde fuente_truetype es el nombre, extensin y path de la fuente TrueType a utilizar (fichero .ttf), fuente_afm es el nombre del fichero.afm creado para esta misma fuente mediante ttf2ufm. Estos dos parmetros son obligatorios. Mediante el parmetro incrustado (por defecto true) se especifica si la fuente va a ser incrustada en los documentos pdf que la utilicen. El parmetro codificacin permite especificar el mapa de fuentes a utilizar. Si no se indica toma el valor por defecto que es cp1252. Por ltimo el paramtro opcional modificadores permite cambiar la codificacin de algunos caracteres.
La ejecucin de la funcin MakeFont() comentada anteriormente podra hacerse mediante un script similar a este:
<?php # incluimos el fichero makefont.php que est # en la ruta que se especifica (si lo tuvieramos en otra # ubicacin bastara cambiar el path del include include($_SERVER['DOCUMENT_ROOT']."/php/tcpdf/fonts/utils/makefont.php"); # ejecutamos la funcin MakeFont indicando como parametros # la ruta y el fichero ttf a convertir(la fuente trueType) # y como segundo parmetro la ruta y el nombre del fichero afm # creado en el proceso anterior MakeFont($_SERVER['DOCUMENT_ROOT']."/php/tcpdf/fonts/utils/bobcayge.ttf", $_SERVER['DOCUMENT_ROOT']."/php/tcpdf/fonts/utils/bobcayge.afm")){ ?>
cuya ejecucin de ese script dara como resultado la creacin en el directorio actual (es decir en el que contenga el script anterior) de dos ficheros con el mismo nombre y extensiones .z y .php. para poder usar la nueva fuente es necesarios incluirlos (ambos) en el directorio/tcpdf/fonts/.
Diferentes tipografas
Lo habitual es que entre las fuentes TrueType de un tipo determinado existan varios ficheros. Uno para la fuente normal, otro para la cursiva, etctera. Cuando se trabaja con este tipo de fuentes y se pretende usar estilos distintos, lo aconsejable es definir una fuente para cada tipo y tratarlos, a la hora de escribir el cdigo de los script como fuentes independientes. De esta forma podramos tener parejas de ficheros del estilo: fxx_normal.z y fxx_normal.php; fxx_cursiva.z y fxx_cursiva.php, etctera. A la hora de utilizarlas se hara como si se tratara de fuentes de distintas familias y habra de evitarse incluir el estilo en SetFont. Por tanto, la sintaxis de la asignacin de fuentes habra de ser: $objeto->SetFont("nombre","", 9);
dejando el valor del segundo parmetro (estilo) como una cadena vaca. La nica excepcin a esta norma sera el caso del subrayadado que no requiere otra cosa que asignar el valor U al parmetro estilo.
En estos dos ejemplos pueden verse los resultados -con algunos problemas grficos- de la sustitucin de las fuentes en algunos de los ejemplos de pginas anteriores.
ejemplo358.php ejemplo359.php
Ficheros MariaDB y/o MySQL Los servidores de bases de datos MariaDB y MySQL
Una de las opciones ms interesantes de PHP es la posibilidad de gestionar bases de datos alojadas en equipos remotos. Existen multitud de aplicaciones de servidor de bases de datos (FilePro, dBase, DBM, Microsoft SQL, PostgreSQL, mSQL, InterBase, MariaDB yMySQL, entre otros) y PHP dispone de recursos para el manejo de todas las mencionadas. Hemos optado por MySQL atendiendo a su disponibilidad en el servidor que aloja este dominio. MySQL utiliza el lenguaje SQL(acrnimo de Structured Query Language, es decir, Lenguaje estructurado de consultas) que hasta el momento ha
sido contemplado como un estandar para gestin de bases de datos. Falta por ver cual ser la evolucin futura en cuanto a gratuidad y servicio. El cambio de propietarios ha generado una cierta inquietud en ese sentido en muchos de los mentideros de la red. Sea cual fuere esa evolucin futura los scripts desarrollados para MySQL son perfectamente compatibles con MariaDB, servidor de bases de datos desarrollado dentro de Open Database Alliance, un consorcio neutral diseado para convertirse en el centro de la industria de la base de datos de cdigo abierto.
Cuidado! Todos los ejemplos que incluimos aqu funcionan sin necesidad de hacer ninguna modificacin en servidores de bases de datos MariaDB.
Las carpetas del subdirectorio data corresponden a cada una de las bases de datos que contiene
Cada una de las tablas que contiene una base de datos requiere tres ficheros de extensiones .frm, MYD y MYI
Cada fichero con extensin .frm contienen la estructura de una tabla. Es en alguna medida una especie de formulario en blanco oformulario tipo. Los ficheros que tienen extensin MYD contiene los datos y aquellos que acaban .MYI contienen los ndices de cada tabla que cumplen una funcin idntica a los ndices de los libros. Por medio de ellos resulta mucho ms rpido encontrar una determinada informacin y al igual que ocurre con los libros ndice general, onomstico, etctera pueden ser varios y de tipos distintos. La base de datos mysql creada durante la instalacin incluye una serie de tablas necesarias para la gestin del servidor. Una de ellas (puedes verla en la imagen) es la tabla user la ms importante para nuestros fines que contiene informacin relativa a los usuarios del servidor de base de datos tales como: permisos y restricciones de acceso, nombres usuarios, contraseas, etctera.
Cuidado! El uso de los tres ficheros anteriores, es condicin de las tablas tipo MyISAM .Otros tipos, que veremos en temas posteriores, tales como InnoDB almacenan la informacin con una estructura diferente.
La tabla user
Activemos nuestro servidor MySQL de la forma que se indica aqu si tu sistema operativo es Linux Ubuntu. Si se trata de Windowspuedes ver aqu la forma de gestionarlo. Una vez activos el servidor MySQL y Apache ya podemos utilizar phpMyAdmin. Lo habamos instalado en un subdirectorio de htdocs llamado phpmyadmin. As que accedamos a travs de la direccin: http://localhost/phpmyadmin/ y se nos abrir una pgina como la que sigue: phpMyAdmin
Elegiremos la base de datos mysql. Al seleccionar mysql en el men de la izquierda y pulsar sobre mysql (en negro en la parte superior de la lista de tablas) aparecer la lista que est a la derecha de esta imagen.
All vemos la tabla user y un enlace activo que dice Examinar. Si pulsamos sobre l, podremos ver un contenido similar a este que vemos aqu debajo.
Como ves, hay cuatro usuarios y dos de ellos como nombre root y ninguna contrasea han sido creados automticamente durante la instalacin. El cuarto de ellos el usuario pepe es el que hemos creado durante el proceso de instalacin Esta configuracin es insegura ya que con los nombres de usuario por defecto root y sin contrasea cualquiera podra acceder y manipular las bases de datos. Ms adelante podremos borrar esos usuarios pero, por el momento, dejmoslos as y aadamos un nuevo usuario. Si pulsamos la opcin editar (el icono en forma de lpiz que hay a la derecha de la casilla de verificacin del usuario sin nombre se nos abrir una pgina como esta:.
Escribamos localhost en el campo Host, jose en el campo User, josefa en el campo Password y marquemos todas las opciones una lista bastante larga por cierto como YES (Y) y muy importante seleccionemos la funcin PASSWORD para el campo del mismo nombre. Una vez realizado el proceso anterior deber quedarnos como aparece en la imagen. Pulsaremos en el botn Contine que hay al final de la pgina y habremos dado de alta al usuario jose con todos los privilegios para gestionar las bases de datos. Si regresamos de nuevo a Examinar veremos que ya ha sido incluido el nuevo usuario y que el campo contrasea aparece encriptado como consecuencia de haber aplicado la funcin PASSWORD para garantizar la privacidad del usuario. MySQL requiere esta encriptacin. Respecto a los YES, la explicacin es sencilla. Esas opciones permiten habilitar permisos para determinadas operaciones dentro de las bases de datos y lo nico que hemos hecho ha sido conceder todas la facultades de gestin al usuario pepe.
donde $conexion es la variable que recoge el identificador del enlace, servidor es la direccin del servidor de bases de datos, ("127.0.0.1" o 'localhost') , usuario es el nombre de uno de los usuarios registrados en la tabla user ("pepe" o "root") y contrasea la contrasea (en nuestro caso "pepa" "") . Estos tres valores cadenas de texto deben ir escritos entre comillas. Para cerrar la conexin utilizaremos la funcin: mysql_close ($conexion)
donde $conexion es el nombre de la variable en la que se recogi el indentificador del enlace en el momento de la apertura. Aqu tienes el cdigo fuente de un script que realiza la apertura de una conexin y despus la cierra y desde aqu puedes comprobar su funcionamiento. Si realizramos una segunda conexin (con los mismos argumentos) sin haber cerrado la anterior no se efectuar un nuevo enlacesino que nos devolver el anterior.
Sintaxis alternativa
Otra forma de efectuar la conexin es utilizar los valores registrados en el fichero mysql.inc.php lo hemos creado en la pgina anterior y eso requiere que insertemos en los scripts un include("C:/ServidoresLocales/Apache/seguridad/mysql.inc.php")(include("/var/seguridad/mysql.inc.php") en el caso de Ubuntu) o, si has elegido otra ubicacin, la ruta completa hasta el fichero en el que hemos guardado las claves de conexin y para el que te hemos sugerido el nombre de mysql.inc.php. En este supuesto como valores de los parmetros servidor, usuario y contrasea pondremos los nombres de las variables:$mysql_server, $mysql_login y $mysql_pass sin encerrarlas entre comillas. Aqu tienes el cdigo de un script que realiza la apertura de una conexin y despus la cierra y desde este enlace puedes comprobar el funcionamiento de esta sintaxis alternativa.
La instruccin OR DIE
Es esta una buena ocasin para hablar de una instruccin PHP que no hemos mencionado hasta el momento. Se trata de una opcin alternativa a exit() que, como acabamos de ver en un ejemplo, interrumpe la ejecucin de un script en el momento de ser ejecutada. Cuando se produce un error en la ejecucin de un script no poder establecer conexin con MySQL, por ejemplo no tiene sentido seguir ejecutndolo. Lo razonable ser interrumpir el proceso y advertir del error. Si aadimos or die ('mensaje') a la instruccin$conexion=mysql_conect('servidor','usuario','contrasea') (sin parntesis, ni comas, ni punto y coma, slo separado por un espacio) y ponemos el punto y coma de fin de instruccin despus de cerrar este ltimo parntesis $conexion=mysql_conect('servidor','usuario','contrasea') or die ('mensaje')
en el caso de que se produzca un error se interrumpir la ejecucin del script y aparecer en la ventana del navegador el texto incluido en mensaje. Este es el cdigo fuente de un script que produce un error la contrasea es incorrecta y que utiliza esta nueva sintaxis. Pero si lo ejecutas vers que aparece un mensaje de error generado por PHP. Este tipo de mensajes pueden deshabilitarse de la forma descrita aqu. Pero hay una tcnica mucho ms fcil. Bastar con insertar delante de la funcin una arroba (@) para evitar que aparezcan. En este otro script lo hemos incorporado y puedes comprobarlo aqui.
dnde la variable $identificacor es un nuevo identificador imprescindible y previo a la determinacin del nmero y los nombres de las bases de datos existentes en el enlace abierto (identificado por $conexion). $numero=mysql_num_rows($identificador)
devuelve en la variable $numero el nmero de bases de datos existentes en el servidor y utiliza como parmetro ($identificador) el resultado obtenido mediante la funcin anterior. mysql_db_name($identificador, indice)
devuelve el nombre de la bases de datos identificada por el nmero indice que debe pertenecer al intervalo [0,$n). Fjate que i tiene que ser i<$n porque si, por ejemplo, $n=5 los cinco valores posibles de i seran: 0,1,2,3 y 4. Una lista completa de todas las bases de datos existentes en el servidor podra hacerse mediante el siguiente proceso: Abrir la conexin.
Invocar a mysql_list_dbs. Contar el nmero de bases de datos con mysql_num_rows Insertar un bucle: for ($i=0;$i<$num,$i++) Presentar la lista de nombres mediante un bucle que lea los diferentes valores de $i en mysql_db_name($identificador,$indice) Aqu tienes el cdigo fuente de un ejemplo completo y desde aqu puedes ejecutarlo
dnde nombre es el nombre de la nueva base de datos. Esta funcin devuelve TRUE si la base de datos es creada, y FALSE si no es posible hacerlo. Si intentamos crear una base de datos con un nombre ya existente la funcin nos devolver FALSE. Aqu tienes el cdigo de un ejemplo de creacin de una base de datos. Si lo ejecutas dos veces podrs comprobar que en la segunda oportunidad te aparece el mensaje diciendo que no ha sido posible crearla. Para evitar esa incomodidad se suele usar la segunda de las sentencia. Cuando se incluye IF NOT EXISTS la base de datos se crea nicamente en el caso de no existir pero, a diferencia de la otra opcin, en caso de que ya existiera no produce ningn mensaje de error.
donde nombre es el nombre de la base de datos y debiendo ponerse toda la cadena del parntesis entre comillas. Esta funcin devuelve TRUE cuando se ejecuta con xito, y FALSE en el caso contrario. Este es el cdigo de un script que puede borrar la base creada anteriormente. Igual que ocurra al tratar de crearla, si intentamos borrar una base de datos inexistente nos devolver FALSE.
Automatizar la conexin
Con nuestros conocimientos sobre PHP ya estamos en condiciones de hacer ms cmoda la conexin. Creemos una funcin que realice de forma automtica la conexin con MySQL y guardmosla en nuestro fichero mysql.inc.php .
<?php # estas son las variables anteriores $mysql_server="localhost"; $mysql_login="pepe"; $mysql_pass="pepa"; # creemos una nueva variable $c sin asignarle ningn valor # para que pueda recoger el identificador de conexin # una vez que se haya establecido esta $c; # escribamos la funcin que hace la conexin # como pretendemos que el valor del identificador # sea usado fuera de la funcin, para recuperar su valor # pasaremos ese valor por referencia anteponiendo & al # nombre de la variable
function conecta1(&$c){ # para usar las variables anteriores en la funcion # hemos de definirlas como globales global $mysql_server, $mysql_login, $mysql_pass; if($c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){ print "<br>Conexin establecida<br>"; }else{ print "<br>No ha podido realizarse la conexin<br>"; # el exit lo incluimos para que deje de ejecutarse # el script si no se establece la conexin exit(); } } # esta funcin asignar a $c el valor del identificador # # # # repetimos la misma funcin con otro nombre ahora quitaremos el mensaje de conexin establecida consideraremos que si no hay mensaje se ha establecido asi quedar limpia nuestra pgina
function conecta2(&$c){ global $mysql_server, $mysql_login, $mysql_pass; if($c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){ }else{ print "<br>No ha podido realizarse la conexin<br>"; exit(); } } ?>
Si sustituyes el contenido de tu mysql.inc.php por el que tienes aqu arriba puedes eliminar la lneas de comentario al hacerlo estaremos en disposicin de ejecutar scripts como este. Estos ejemplos utilizan cada una de las dos funciones.
Ver cdigo fuente Ver cdigo fuente
este otro cdigo Pulsa en este enlace para que cree automticamente la base de datos que va a contener los sucesivos ejemplos que hemos incluido en estos materiales.
Campos numricos
MySQL soporta los tipos numricos exactos (INTEGER, NUMERIC, DECIMAL, y SMALLINT) y los tipos numricos aproximados(FLOAT, DOUBLE precision y REAL). Los campos que contienen nmeros enteros admiten el parmetro UNSIGNED, que implica que no admita signos, por lo que solo aceptara enteros positivos. Todos los campos numricos admiten el parmetro ZEROFILL cuya funcin es completar el campo con ceros a la izquierda hasta su longitud mxima. Tipos de campos numricos enteros Estos son los distintos tipos de campos numricos enteros que admite MySQL. Los parmetros sealados entre corchetes son opcionales. TINYINT [(M)] [UNSIGNED] [ZEROFILL]
Nmero entero muy pequeo. Con la opcin UNSIGNED puede tomar valores entre 0 y 255. En caso contrario, puede estar comprendido entre -128 y 127. El parmetro ZEROFILL slo tiene sentido junto con la opcin UNSIGNED ya que no es habitual rellenar los nmeros negativos con ceros a la izquierda del signo. El valor por defecto de parmetro M (nmero de cifras) es 4 si no est activada la opcin UNSIGNED. Si esta opcin estuviera activada el valor por defecto seraM=3. Para valores de M >valor por defecto reajusta el tamao al valor por defecto. Si se asigna a M un valor menor que cuatro limita el nmero de caracteres al tamao especificado considerando el signo slo en los nmeros negativos. Por ejemplo, si M=3 admitira 148, pero si intentamos insertar -148 recortara por la izquierda y solo insertara -14. Si intentamos insertar un valor fuera de rango registrara el valor dentro del rango ms prximo a l. P. ej.: Si tratamos de insertar el valor 437 escribira 127 255, este ltimo en el caso de tener la opcin UNSIGNED. Si pretendiramos insertar -837 con la opcin UNSIGNED escribira 0 y sin ella pondra -128. El tamao de un campo TINYINT es de 1 byte.
Tambin son vlidos los comentarios hechos para TINYINT, excepto los relativos al valor por defecto de M que en este caso seran 8. Su tamao es de 3 bytes.
FLOAT(x) [ZEROFILL]
Nmero de coma flotante. Ignora la opcin UNSIGNED, pero s acepta ZEROFILL, por lo que debe prestarse atencin a estas opciones ya que no sera demasiado habitual una presentacin como esta: 000-3.47 El valor de x especifica la precisin. Si x<=24 ser de precisin simple. cuando 24 <x <=53 lo convertir automticamente a doble precisin. Cuando no se especifica el valor de x considera el campo como de precisin simple. Su tamao es de 4 bytes si x<=24 y de 8 bytes cuando 24 <x <=53
-1.7976931348623157E+308 a -2.2250738585072014E-308 0y 2.2250738585072014E-308 a 1.7976931348623157E+308 M es la anchura mxima de visualizacin y D es el nmero de decimales. DOUBLE sin argumentos representa un nmero de coma flotante y precisin doble.
NUMERIC(M,D) [ZEROFILL]
Se comporta de forma idntica a DECIMAL
Campos de fecha
MySQL dispone de campos especficos para el almacenamiento de fechas. Son los siguientes: DATE
Recoge una fecha dentro del intervalo 01-01-1000 a 31-12-9999. MySQL guarda los valores DATE con formato AAAA-MM-DD (ao-mes-da) . Su tamao es de 3 bytes.
DATETIME
Recoge una combinacin de fecha y hora dentro del intervalo 00:00:00 del da 01-01-1000 y las23:59:59 del da 31-12-9999. MySQL guarda los valores DATETIME con formato AAAA-MM-DD HH:MM:SS (ao-mes-da hora:minutos:segundos) . Su tamao es de 8 bytes.
TIME
Recoge una hora dentro del intervalo -838:59:59 a 838:59:59. MySQL guarda los valores TIME con formato HH:MM:SS (horas:minutos:segundos) . Su tamao es de3 bytes.
TIMESTAMP [(M)]
Recoge un tiempo UNIX. El intervalo vlido va desde 01-01-1970 00:00:00 a cualquier fecha del ao 2037. El parmetro M puede tomar los valores: 14 (valor por defecto), 12, 8, o 6 que se corresponden con los formatos AAAAMMDDHHMMSS, AAMMDDHHMMSS,AAAAMMDD, o AAMMDD. Si se le asigna la opcin NUL guardar la hora actual. Cuando se asigna 8 o 14 como parmetros es considerado como un nmero y para las dems opciones comouna cadena. Independientemente del valor del parmetro, un campo TIMESTAMP siempre ocupa 4 bytes.
VARCHAR(M) [BINARY]
Es una cadena de caracteres de longitud variable. Su tamao mximo -especificado en el parmetro M- puede estar comprendido entre 1 y 255 caracteres. Con la opcin BINARY es capaz de discriminar entre Maysculas / minsculas.
TINYBLOB o TINYTEXT
TINYBLOB y TINYTEXT son cadenas de caracteres de longitud variable con un tamao mximo de 255 (28 - 1) caracteres. La diferencia entre ambas es que TINYBLOB discrimina entre Maysculas / minsculas, mientras que TINYTEXT no lo hace. Ninguno de los campos BLOB y TEXT admite valores por DEFECTO Las versiones de MySQL anteriores a 3.23.2 permiten utilizar estos campos para indexar. Si se intenta guardar en un campo de este tipo una cadena de mayor longitud que la especificada solamente se guardarn los M primeros caracteres de la cadena.
BLOB o TEXT
BLOB y TEXT son cadenas de caracteres de longitud variable con un tamao mximo de 65535 (216 - 1) caracteres. La diferencia entre ambas es que BLOB si discrimina entre Maysculas / minsculas, mientras que TEXT no lo hace. Ninguno de los campos: BLOB y TEXT admite valores por DEFECTO
MEDIUMBLOB o MEDIUMTEXT
MEDIUMBLOB y MEDIUMTEXT son cadenas de caracteres de longitud variable con una longitud mxima de 16.777.215 (224 - 1) caracteres. Son vlidas las especificaciones hechas en el apartado anterior. El tamao mximo de los campos de este tipo est sujeto a limitaciones externas tales como la memoria disponible y el tamao del buffer de comunicacin servidor/cliente.
LONGBLOB o LONGTEXT
Su nica diferencia con la anterior es el tamao mximo de la cadena, que en este caso es 4.294.967.295 (232 - 1) caracteres.
ENUM('valor1','valor2',...)
Es una cadena de caracteres que contiene uno solo de los valores de la lista (valor1, valor2, etc. etc.). A la hora de insertar un nuevo registro en una tabla, el valor a especificar para un campo de este tipo ha de ser una cadena que contenga uno de los valoresespecificados en la tabla. Si se tratara de insertar un valor distinto de ellos insertara una cadena vaca.
SET('valor1','valor2','valor3'...)
Es una cadena de caracteres formados por la unin de ninguno, uno o varios de los valores de una lista. El mximo de elementos es 64. Los valores que deben escribirse en los campos de este tipo han de ser numricos, expresados en forma binaria o en forma decimal. En el supuesto de que contuviera tres valores los posibles valores a insertar en un campo de este tipo a la hora de aadir un registro seran los siguientes.
Cadena Equiv. val1 val2 val3 val1 val2 val3 binaria decimal
Si Si Si
S S
1 1 0 0
1 1 0 1 0 1
1 0 1 1 1 0
7 3 5 6 4 2
No 1 S
No S
No S No S
No No S
NO 0
Si
No No 1
0 0
0 0
001 000
1 0
No No No 0
Creacin de tablas
Las tablas son elementos de las base de datos. Por esa razn nos resultar imposible crear una tabla sin tener creada yseleccionada una base de datos. Es por eso que para la creacin de una tabla se necesitan los siguientes requisitos: Tener abierta una conexin con el servidor MySQL. Tener seleccionada una base de datos.
donde nombre_base_datos es el nombre de la base de datos (puede ser una cadena entrecomillada o el nombre de una variable previa que contenga ese nombre). En este ltimo caso, como es habitual, el nombre de la variable no llevara comillas. El segundo parmetro$conexion es el identificador de conexin. Es decir, la variable creada al establecer la conexin con MySQL. Este valor debe insertarse siempre. La razn es que MySQL permite mantener abiertas varias, de forma simultnea, varias conexiones (podramos manejar ms de un servidor de bases de datos) y en esas condiciones no pueden darse ambigedades respecto a la base que pretendemos usar.
mysql_query("sentencia", $conexion);
donde la cadena sentencia contiene las instrucciones propias de MySQL y $conexion sigue siendo la variable que contiene el identificador de conexin. La creacin de tablas MySQL requiere una de estas dos sentencias: CREATE TABLE IF NOT EXISTS tabla (campo1, campo2,... ) Type=tipo o CREATE TABLE tabla (campo1, campo2,... )) Type=tipo
donde tabla es una cadena que contiene el nombre de la tabla que pretendemos crear, dnde campo1, campo2, etc. son las definiciones de los campos que pretendemos que contenga la tabla y tipo puede ser MyISAM o InnoDB segn el tipo de tabla que queramos crear. La nica diferencia entre ambas opciones es que la segunda dara un error si tratramos de crear una tabla preexistente (deberamos recurrir al procedimiento que hemos visto cuando crebamos bases de datos) mientras que la primera no da ese mensaje de error.
Es una palabra cualquiera distinta para campo de la tabla y que normalmente suele elegirse aludiendo al contenido. Por ejemplo,fecha_nacimiento, nombre_del_perro, etctera. No va entre comillas nunca y MySQL diferencia maysculas/minsculas. Para utilizar como nombres de campo palabras reservadas del lenguaje MySQL por ejemplo, create debemos escribirlas entre ` `. Observa que no son comillas sino acentos graves. Lo ms aconsejable es evitar esta situacin. tipo y dimensiones
Los tipos de campos los hemos visto en la pgina anterior tienen que ajustarse a uno de los soportados por MYSQL. El tipo de campo se escribe a continuacin del nombre sin otra separacin que un espacio y requieren la sintaxis estricta correspondiente a cada tipo. Cuando se establezca una dimensin como parmetro opcional de un campo deben tenerse en cuenta algunos detalles: Su valor se escribe entre parntesis y se incluye despus del nombre del campo. Si en un campo numrico introdujramos valores que exceden los lmites, su valor no se registrara en la tabla sino el valor dellmite ms prximo correspondiente a ese tipo de campo. Supongamos un campo tipo TINYINT que permite valores comprendidos entre -128 y 127. Si asignramos en uno de sus registros un valor igual a 234 se escribira en la tabla 127 (el lmite superior) y si ponemos -834 escribira el lmite inferior, es decir, -128. En caso de cadenas, si el valor introducido sobrepasara la longitud mxima permitida, la cadena sera recortada y nicamente se registrara el nmero mximo de caracteres permitidos. flags del campo ( son opcionales) Puede utilizarse cualquiera de los permitidos para cada tipo de campo. Puedes verlos encerrados, entre corchetes, al lado de cada tipo de campo. Cuando sea necesario incluirlo han de escribirse inmediatamente despus del nombre del campo o de la dimesin (en los casos en que se incluya).
<?php /* nos conectamos con el servidor recogiendo en $c el identificador de conexin */ $c=mysql_connect ("localhost","pepe","pepa") or die ("Imposible conectar"); # seleccionamos una base de datos existente # de lo contrario nos dara un error # pondremos como nombre ejemplos nuestra base de datos # creada en la pgina anterior y usaremos $c # importante no olvidarlo mysql_select_db ("ejemplos", $c); /* ahora ya estamos en condiciones de crear la tabla podramos escribir ya la instruccin mysql_query y meter detro la sentencia MySQL pero, por razones de comodidad crearemos antes una variable que recoja toda la sentencia y ser luego cuando la ejecutemos. Definiremos una varable llamada $crear e iremos aadiendo cosas */ # la primera parte de la instruccin es esta (espacio final incluido $crear="CREATE TABLE IF NOT EXISTS "; # aadiremos el nombre de la tabla que ser ejemplo1 # fijate en el punto (concatenador de cadenas) que permite # ir aadiendo a la cadena anterior $crear .="ejemplo1 "; #ahora pongamos el parntesis (con un espacio delante) #aunque el espacio tambin podra detrs de ejemplo1 $crear .="( "; # insertemos el primer campo y llamemoslo num1 # hagamoslo de tipo TINYINT sin otras especificamos # sabiendo que solo permitira valores numricos # comprendidos entre -128 y 127 $crear .="num1 TINYINT , "; # LOS CAMPOS SE SEPARAN CON COMAS por eso # la hemos incluido al final de la instruccin anterior # ahora num2 del mismo tipo con dimensin 3 y el flag UNSIGNED # Y ZEROFILL que: cambiar los lmites de valores # al intervalo 0 - 255, y rellenar con ceros por la izquierda # en el caso de que el nmero de cifras significativas # sea menor de 3. # Fijate que los flags van separado unicamente por espacios $crear .="num2 TINYINT (3) UNSIGNED ZEROFILL, "; # en num3 identico al anterior aadiremos un valor por defecto # de manera que cuando se aadan registros a la tabla # se escriba automaticamente ese valor 13 en el caso # de que no le asignemos ninguno a ese campo # por ser numrico 13 no va entre comillas $crear .="num3 TINYINT (7) UNSIGNED ZEROFILL DEFAULT 13, "; # ahora un nmero decimal num4 tipo REAL con 8 digitos en total # de los cuales tres sern decimales y tambin rellenaremos con ceros # Pondremos como valor por defecto 3.14 $crear .="num4 REAL (8,3) ZEROFILL DEFAULT 3.14, "; # aadamos una fecha $crear .="fecha DATE, "; /* una cadena con un limite de 32 carcter con BINARY para que diferencie Pepe de PEPE */ $crear .="cadena VARCHAR(32) BINARY, "; /* un ultimo campo opcion del tipo ENUM que solo admita como valores SI, NO, QUIZA fijate en las comillas y en el parentesis cuidado...!! aqui no ponemos coma al final es el ltimo campo que vamos a insertar y no necesita ser separado. Si la pones dar un ERROR */ $crear .="opcion ENUM('Si','No','Quiza') ";
# solo nos falta aadir el parntesis conteniendo toda la instruccin $crear .=")Type=MyISAM"; /* tenemos completa la sentencia MYSQL solo falta ejecutarla mediante mysql_query ya que la conexin est abierta y la base de datos ya est seleccionada */ /* pongamos un condicional de comprobacin */ if(mysql_query($crear,$c)){ print "Se ha creado la base de datos<br>"; print "La sentencia MySQL podramos haberla escrito asi:<br>"; print "mysql_query("."\"".$crear."\" , $c);"; }else{ print "Se ha producido un error al crear la tabla"; } ?>
$resultado=mysql_query(sentencia,$conexion); while($linea=mysql_fech_row($resultado){ foreach ($linea as $valor){ print $valor; } } tambin cabra usar una sintaxis alternativa similar a esta: $resultado=mysql_query(sentencia,$conexion); while($linea=mysql_fech_row($resultado)){ $matriz[]=$linea; } con lo que estaramos creando un array bidimensional con el contenido de los resultados de cada lnea. En este caso el primer ndicedel array $matriz sera un escalar que empezara en cero y se ira autoincrementando en una unidad en cada uno de los ciclos del buclewhile. El ejemplo tiene desarrollados ambos procedimientos.
<?php # asignamos a una variable el nombre de la base de datos $base="ejemplos"; # esta otra recoge el nombre de la tabla $tabla="ejemplo1"; # establecemos la conexin con el servidor $conexion=mysql_connect ("localhost","pepe","pepa"); # seleccionamos la base de datos mysql_select_db ($base, $conexion); #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=mysql_query( "SHOW FIELDS from $tabla",$conexion); # ejecutamos los bucles que comentamos mas arriba while($linea=mysql_fetch_row ($resultado)){ foreach($linea as $valor) { print $valor."<br>"; } } #tenemos que VOLVER a EJECUTAR LA SENTENCIA MySQL porque el puntero est # AL FINAL de la ultima lnea de los resultados print("<BR> Los nuevos resultados son <br>"); $resultado=mysql_query( "SHOW FIELDS from $tabla",$conexion); while($linea=mysql_fetch_row ($resultado)){ $matriz[]=$linea; } # leemos ahora el array bidimensional foreach ($matriz as $indice=>$mi_linea){ foreach ($mi_linea as $indice2=>$valor){ print "<i>Indice</i>: ".$indice." <i>Indice2</i>: ".$indice2." <i>Valor</i>: ".$valor."<br>"; } } # cerramos la conexion con el servidor mysql_close($conexion); ?>
ejemplo373.php
El procedimiento anterior nos facilita informacin sobre la estructura de la tabla pero quiz no lo haga con toda la claridad que fuera de desear. Para mejorar las prestaciones de la anterior existe una funcin alternativa que es:
$matriz =mysql_fetch_array($resultado) idntica en cuanto a requerimientos pero recogiendo en un array los resultados de la sentencia. Ese array tiene adems la peculiaridad de incluye cada uno de los valores en dos ndices distintos. Uno de los ndices es de tipo escalar. El otro es de tipo asociativo y sus ndices son los valores del campo de la tabla del que se han extraido los resultadosativos. En este ltimo caso incorporan como ndice el nombre del campo de la tabla del que se han extrado los resultados. $matriz =mysql_fetch_array($resultado, MYSQL_NUM) idntica a la anterior.La inclusin del parmetro MYSQL_NUM (sin comillas )limita sus resultado a los elementos del array de ndice escalar. $matriz =mysql_fetch_array($resultado, MYSQL_ASSOC) Tambin idntica a las anteriores. La inclusin del parmetro MYSQL_ASSOC (sin comillas )limita ahora los resultado a los elementos del array asociativo.
<?php # asignamos a una variable el nombre de la base de datos $base="ejemplos"; # esta otra recoge el nombre de la tabla $tabla="ejemplo1"; # establecemos la conexin con el servidor $conexion=mysql_connect ("localhost","pepe","pepa"); # seleccionamos la base de datos mysql_select_db ($base, $conexion); #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=mysql_query( "SHOW FIELDS from $tabla",$conexion); print("<br> Los resultados con mysql_fech_array<br><br>"); while ($linea=mysql_fetch_array($resultado)){ # leemos el array de resultados de cada una de las lineas extraidas del resultado foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* vamos a separar los elementos escalares de los asociativos comprobando si es numrico el indice de cada array */ print "<br>Los elementos de array con indice numrico son estos<br>"; $resultado=mysql_query( "SHOW FIELDS from $tabla",$conexion); while ($linea=mysql_fetch_array($resultado,MYSQL_NUM)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* visualizamos los resultados cuando el indice es NO NUMRICO */ print "<br>Los elementos de array con indice no numrico son estos<br>"; $resultado=mysql_query( "SHOW FIELDS from $tabla",$conexion); while ($linea=mysql_fetch_array($resultado, MYSQL_ASSOC)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) {
print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } mysql_close($conexion); ?>
ejemplo374.php
Como habrs podido observar al ejecutar el ejemplo SHOW FIELDS nos permite conocer los propiedades de cada uno de los campos de la tabla: Field (nombre del campo), Type (incluye el tipo, el tamao y los flags), Null (especificara si el campo permite o no permite valores nulos), Key (especificara si ese campo es o es un ndice de la tabla) y Default (que incluira los eventuales valores asignados por defecto al campo).
Liberando memoria
Si queremos liberar la parte de la memoria que contiene un identificador de resultado, bastar con que insertemos la siguiente instruccin: mysql_free_result($resultado)
Manipulacin de tablas
Borrar tablas
Las sentencias MySQL que permiten borrar una tabla son las siguientes: DROP TABLE IF EXISTS from nombre_de_la_tabla o DROP TABLE from nombre_de_la_tabla la diferencia entre ambas radica en que usando la primera no se generara ningn error en el caso de que tratramos de borrar una tabla inexistente. Aqu tienes el cdigo fuente de un ejemplo:
Ver cdigo fuente
Facilitar la bsqueda de datos Agilizar esa bsqueda La utilidad de los ndices en la bases de datos es bastante similar. Si seguimos con el ejemplo del libro veremos que caben las posibilidades de que tenga: Un solo ndice Varios ndices Algunos libros slo contienen un indice de contenidos. Sin embargo, es frecuente que tambin dispongan de otros, tales como:ndices analticos, ndices onomsticos, etctera. Cuando existe un solo ndice es obvio que puede decirse de l que es nico y cuando existen varios podemos decir que el ndice de contenidos es el ndice principal y los dems son ndices sin ms o ndices auxiliares. Coincidirs con nosotros en que en el ndice de contenidos de un libro de texto slo existe una referencia al Tema XIII en la que puede decir: Tema XIII pgina 314. Tambin coincidirs en que si en ese ndice, adems de lo anterior, dijera: Tema XIII pgina 714 nos encontraramos en una situacin confusa que nos obligara a preguntarnos: donde est el Tema XIII? En la pgina 314? En la 714? En ambas?. Es por eso que las tablas de las bases de datos no admiten nunca valores duplicados ni en los ndices nicos ni tampoco en losndices principales. Los ndices auxiliares tienen un comportamiento distinto. El ndice onomstico de un libro puede hacer referencia a varias pginas y puede tener duplicados. Por ejemplo: en un manual de Word puede existir un ndice onomstico en el que se asocie la palabramacros con las pginas 37, 234 y 832 siempre que en esas pginas existan contenidos que aludan a la palabra macro. Es por eso que las tablas de las bases de datos tambin admiten duplicados cuando se trata de ndices auxiliares.
Creacin de la tabla
Empezaremos creando una tabla a la que llamaremos demo4 y que contendr los siguientes campos: Contador, que ser de tipo TINYINT(8) (nmero entero con un mximo de 8 dgitos) que contenga solo valores positivos, que se rellene automticamente con ceros por la izquierda y que se autoincremente cada vez que aadimos un registro. DNI, destinado a recoger valores de nmeros de DNI y que debe poder contener un mximo de ocho caracteres. Lo definiremos de tipo CHAR porque sus valores, pese a ser numricos, nunca van a requerir ningn tratamiento aritmtico. Nombre, Apellido1 y Apellido2 sern tres campos tipo VHAR de tamaos mximos respectivos de 20, 15 y 15 caracteres. Su finalidad la evidencian los nombres de campo. Les asignaremos el flag NOT NULL aunque no sea totalmente correcto dado que existen pases en los que se utiliza un solo apellido. Nacimiento ser un campo tipo DATE al que asignaremos como valor por defecto el de 1970-12-21. Recuerda que MySQL trata las fechas en ese orden (ao-mes-dia) y que admite como separadores tanto - como / por lo que son vlidas entradas con cualquiera de estos formatos: 1970-12-21 1970/12/21, aunque esta segunda es convertida automaticamente al primer formato por MySQL. Hora ser un campo tipo TIME al que asignaremos como valor por defecto el de 00:00:00. Recuerda que MySQL trata las horas en ese orden (hh:mm:ss) y que slo admite como separador :. Este campo est destinado a recoger la hora de nacimiento que aunque no tiene demasiado sentido es una buena excusa para introducir este tipo de campo. Sexo ser un campo tipo ENUM que tendr dos opciones: M (masculino) y F(femenino) y al que asignaremos M como valor por defecto. Fumador ser un campo tipo CHAR(0) que por su estructura -cadena de longitud cero- tendr dos nicas opciones de valor: NULL "", que, como veremos, son valores distintos para MySQL.
Idiomas ser un campo tipo SET definido para los valores: Castellano, Francs, Ingls, Alemn, Blgaro y Chino y que podr contener, como ocurre con los campos de este tipo, ninguno, uno o varios de los valores de la lista. ndice primario ser tratado como tal el campo DNI ya que se trata de un valor nico para cada persona y que, como tal, no puede tener duplicados. ndices auxiliares. Para ejemplificar su tratamiento consideraremos el campo Contador como ndice secundario. El cdigo fuente del fichero que genera esta tabla puedes verlo aqu debajo
Ver cdigo fuente
Aadir un registro
Cuando se aade un registro en una tabla los valores pueden aadirse en la propia sentencia MySQL o ser recogidos de los valores de variables PHP previamente definidas. En este ejemplo tienes el cdigo fuente del primero de los casos, en el que se aade a la tabla anterior un registro cuyos valores son:
DNI Nombre Apellido1 Apellido2 Nacimiento Sexo Hora Fumador Idiomas
16:24:52 NULL
Presta atencin a los siguientes aspectos: En la sentencia no se alude al campo Contador. La razn es que se trata un campo AUTOINCREMENTAL y en ese tipo de campos los valores de los registros se escriben automticamente cada vez que se aade uno nuevo. El registro no se aadira si el valor de DNI coincidiera con otra ya existente en la tabla. Recuerda que habamos definido ese campo como ndice primario. Si no hubiramos incluido el aviso de error no tendramos ninguna referencia sobre el xito de la insercin y no detectaramos el problema de duplicidad. Sencillamente ocurrira que el registro no se aadira pero no nos enteraramos de tal circunstancia. Si en los valores de nombre y apellidos hubiramos insertado textos ms largos del tamao establecido para ellos al crear la tabla, las cadenas se recortaran y slo se aadiran -de izquierda a derecha- los n primeros caracteres de la cadena. Si en la fecha de nacimiento hubiramos introducido una cadena vaca nos habra puesto el valor por defecto, pero si hubiramos introducido un valor no vlido nos habra escrito 0000-00-00. Seran valores no vlidos en este caso: Los que tuvieran como valor de mes alguno no perteneciente al intervalo [1,12]. Los que tuvieran como valor de da un valor no vlido en concordancia con el mes y el ao. Admitira 29 en un mes defebrero slo en el caso de que el ao fuera bisiesto. Cuando la secuencia no coincidiera con esta AAAA-MM-DD. Cuando los separadores no fueran (-) o (/). En el campo Sexo si hubiramos introducido una cadena vaca nos habra puesto M (valor por defecto) pero si hubiramos intentado introducir un valor que no fuera M ni F nos habra insertado una cadena vaca. El campo hora se comportara de idntica forma al de fecha salvo que aqu la secuencia es: hh:mm:ss, que la hora debe pertenecer al intervalo [0,23], los minutos y los segundos a [0,59] y que el nico separador vlido en este caso es (:). El campo Fumador requiere particular atencin ya que se trata de un campo CHAR(0) que slo admite dos valores: NULL ocadena vaca, que como recordars son distintos para MySQL. Para introducir el valor NULL utilizando el procedimiento de insercin de este ejemplo tienes que escribir NULL, sin ponerlo entre comillas, tal como lo he hecho en el ejemplo . Para introducir una cadena vaca en este campo bastara con que pusieramos '' (ojo no es una comilla doble es la comilla sencilla (') repetida dos veces! Date cuenta de que si pusiramos comillas dobles tendramos un error ya que hay unas comillas dobles delante delINSERT que
se cierran al final de la sentencia MySQL y que no podemos volver a escribirlas entre ambas para evitar unfalso cierre de la cadena que contienen. En este caso el valor del campo Idiomas puede contener valores decimales comprendidos entre 0 y 64 o entre sus equivalentes binarios que son 0 y 111111. El valor 64 lo justifica el hecho de que son seis los elementos que puede contener el campo (hemos definido: Castellano, Francs, Ingls, Alemn, Blgaro y Chino que son seis y que el caso de insertarlos todos requerira el nmero binario 111111, cuyo valor decimal es precisamente 64. El valor 3 significa lo mismo que su equivalente binario (11) o mejor (000011) lo cual quiere decir que, como el primer carcter de la derecha es uno el campo toma el primer elemento de la lista (Castellano), como el segundo (de derecha a izquierda) tambin esuno tomar tambin el segundo elemento de la lista (Francs) y por ser cero todos los dems no tomar ningn otro valor de la lista, con lo que la cadena resultante sera en este caso Castellano, Francs. Fjate tambin en que el valor 3 no lo hemos puesto entre comillas porque se trata de una expresin decimal. Qu ocurra si hubiera puesto 11? Lo habra interpretado como once (decimal) o como tres (binario)?. La solucin es simple: '11' (entre comillas) sera interpretado como binario, sin comillas como decimal. No es necesario introducir valores en todos los campos, es decir, que la lista de campos de la sentencia INSERT puede no contenerlos a todos. No es necesario escribir el nombre de los campos en el mismo orden en el que fueron creados pero si es imprescindible quecampos y valores estn escritos en la sentencia INSERT exactamente en el mismo orden y tambin que en esa sentencia elnmero de campos y el nmero de valores sea el mismo. Recuerda que los values tipo numricono se incluyen entre comillas, mientras que los no numricos tienen que estar contenidos entre comillas incluso en el caso de no se inserten directamente sino a travs de una variable PHP.
Quiz te resulten de alguna utilidad estos comentarios: Observa en el cdigo fuente que al insertar las variables en los VALUES de la sentencia MySQL ponemos cuando se trata de valores tipo cadena '$variable' (el nombre de la variable entre comillas) y cuando se trata de valores nmericos sin comillas. Si quieres introducir el valor NULL en un campo tipo VAR(0) define la variable as: $variable="NULL" y si quieres introducir unacadena vaca defnela de este otro modo:$var="''" -comillas dobles (") seguidas de dos comillas sencillas (') y para terminar otras comillas dobles (") y cuando hagas alusin a esa esta variable como un VALUE en la sentencia de insercin no la pongas entre comillas.
dos ordenadores distintos, dos personas distintas estn accediendo a la misma tabla simultneamente y que uno de los accesos sea de escritura, es decir: aadir,modificar o borrar campos en la tabla. Quin tiene preferencia de paso? Quien tiene que esperar?. Si la opcin LOW_PRIORITY est activada, el proceso de escritura esperar a que terminen los procesos de lectura activos, pero si est activa la opcin DELAYED el proceso de lectura se interrumpir automticamente para ceder el paso al de escritura. Respecto a la opcin IGNORE tiene utilidad cuando se trata de realizar una secuencia de inserciones. Si no est activa en el momento en el que aparezca una clave duplicada se interrumpir el proceso de insercin, por el contrario, si estuviera activa el proceso de insercin continuar con los siguientes registros de la secuencia, aunque -como es lgico- seguirn sin insertarse los registros con clave duplicada.
Al ir seleccionando valores, van aadindose al array. Por ejemplo. Si seleccionamos Francs y Blgaro el array sera este: var[0]=2,var[1]=16 Si sumamos esos valores (2 + 16) el resultado sera 18, y al convertir a binario este valor, resultar: 010010 que es como decirle a MySQL (mirando la cadena de derecha a izquierda, lo recuerdas?) que incluya los valores segundo (Francs) y quinto (Blgaro) del SELECT MULTIPLE que corresponden a las posiciones en las que la cadena binaria contiene un uno.
En realidad, tal como habrs podido ver en el cdigo fuente, la depuracin ha sido la siguiente: Hemos creado un valor de fecha y hora en formatos MySQL vlidos de la forma que describimos un poco ms arriba. Hemos sumado todos los valores numricos recibidos en el array obtenido del SELECT MULTIPLE y hemos asignado el resultado a la variable depurada que recoge el valor a escribir en el campo Idiomas. La justificacin de esa suma la tienes al margen. La variable Fumador es la que tiene un poquito ms de complicacin. Vemosla con calma: Los valores que recibimos desde formulario son 1 o 0 y hemos de transformarlos en una cadena vaca o en NULL. Hemos insertado un operador condicional (un if... else) para convertir eso valores en: $var="'\N'" (comilla doble, comilla simple, barra invertida, N, comilla simple y comilla doble) $var="''" (comillas dobles, dos comillas simples y unas comillas dobles) Asignados los nuevos valores tenemos que recurrir a un pequeo truco. Venimos repitiendo que en la sentencia INSERT losnombres de las variables no numricas que contienen los values hay que escribirlos dentro de comillas simples, pero en el caso de un campo tipo CHAR(0) hemos de hacer una excepcin que sera no poner esas comillas al nombre de la variable. Al hacerlo as, se escribiran como valores en la sentencia de insercin uno de estos: ='\N' o =' ' (los valores de la variable) que al contenercomillas ya son interpretados por MySQL como una cadena.
GROUP BY definicion Tiene carcter opcional y su finalidad es la de presentar los resultados de la consulta agrupados segn el criterio establecido en su definicin. Resulta de gran utilidad cuando se pretende obtener valores estadsticos de los registros quecumplen determinadas condiciones (las condiciones del agrupamiento). ORDER BY definicion Tambin tiene carcter opcional y su utilidad es la de presentar la informacin de la consulta ordenada por los contenidos de uno o varios campos. Siempre tiene como opcin complementaria de que en cada campo utilizado para la ordenacinpuede establecerse uno de estos criterios ASC (ascendente, es el valor por defecto) o DESC (descendente). Si no se establece ningn orden los resultados de la consulta aparecern en el mismo orden en el que fueron aadidos los registros. LIMIT m, n Esta clusula es opcional y permite establecer cuntos y cules registros han de presentarse en la salida de la consulta. Por ejemplo: LIMIT 4, 8 indicara a MySQL que la consulta debera mostrar OCHO registros contados a partir del quinto (s, el quinto porque LIMIT considera el primer registro como CERO). El criterio lmite se aplica sobre los resultados de la salida, es decir, sobre los resultados seleccionados, ordenados yfiltrados siguiendo los criterios establecidos por las clusulas anteriores. Si se escribe como un solo parmetro (LIMIT k), MySQL lo interpretar como que k es el segundo de ellos y que el primero es CERO, es decir: LIMIT 0, k
La consulta ms simple
Si utilizamos la sentencia SELECT * FROM tabla obtendremos informacin sobre todos los campos (*) y la salida estar en el mismo orden en el que fueron aadidos los datos. Si visualizas este ejemplo, vers que aparecen ordenados por el valor autonumrico del campo Contador lo cual, como ves, resulta coherente con la afirmacin anterior.
Ejecutar consulta Ver cdigo fuente
Cuidado! En los comentarios contenidos en estos ejemplos puedes ver la forma en la que mysql_fetch_row ymysql_fetch_array tratan los ndices escalares de los resultados que producen los SELECT de MySQL. Los valores de los ndices se asignan a los contenidos de los campos por el mismo orden en el que estos se escriben en la sentencia SELECT. El campo1 (primero que se escribe) ser recogido por el elemento de ndice cero del array, el campo2 ser recogido con ndice uno y as sucesivamente
Ahora utilizaremos la sentencia SELECT campo1,campo2, ... FROM tabla LIMIT (n, m) y tendremos como resultado una lista que contendr m registros a partir del n+1, por el mismo orden que la anterior, y mostrando los campos indicados.
Ejecutar consulta Ver cdigo fuente
Consultas condicionadas
La clasula WHERE permite un variado abanico de condiciones, que trataremos de resumir aqu. Algunos de ellas son los siguientes:
Tipo Sintaxis de campo Numrico WHEREcampo=num Cadena WHEREcampo="cadena" Cdigo Ver fuente ejemplo Ver Ver Ver Ver Ver Probar Probar Probar Probar Probar
Operador
Descripcin Selecciona los registros que contienen en el campo un valor igual a num Selecciona los registros que contienen en el campo una cadena idntica a cadena (*) Selecciona los registros que contienen en el campo un valor menor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmenores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**) Selecciona los registros que contienen en el campo un valor menor O igual a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmenores que los de la cadena, siendo n el nmero de caracteres que contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo un valor mayor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmayores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**)
Numrico WHEREcampo<=num
Cadena
WHEREcampo<="cadena"
Ver
Probar
Ver Ver
Probar Probar
>= >=
Numrico WHEREcampo>=num
Selecciona los registros que contienen en el campo un valor mayor o igual a num Ver Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmayores que los de la cadena, siendo n el nmero de caracteres que contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo valores que coinciden con alguno de los especificados dentro del parntesis. Cuando se trata de valores no numricoz han de ir entre comillas
Probar
Cadena
WHEREcampo>="cadena"
Ver
Probar
IN
Ver
Probar
Selecciona los registros en los que los valores contenidos en el campo seleccionado estn comprendidos en el intervalo valor1 (mnimo) valor2 (mximo) incluyendo en la seleccin ambos extremos. Ver Cuando los contenidos de los campos son cadenas sigue los mismos criterios que se indican para los dems operadores de comparacin Selecciona los registros en los que los valores contenidos en el campo seleccionado son NULOS Selecciona los registros en los que los valores contenidos en el campo seleccionado son NO NULOS Ver Ver
Probar
Cadena Cadena
Probar Probar
(*) Cuando se trata de cadenas de caracteres, el concepto menor que significa anterior en la ordenacin de los caracteres segn su cdigo ASCII y mayor quesignifica posterior en esa misma ordenacin. (**) La discriminacin de Maysculas/Minsculas depender del tipo de campo. Recuerda que los tipo BLOB hacen esa discriminacin, mientras que los de tipo TEXT son insensibles a Maysculas/Minsculas.
Cuando se trata de comparar cadenas MySQL dispone de una potente instruccin (LIKE) que permite establecer los criterios de seleccin a toda o parte de la cadena. Su sintaxis contempla distintas posibilidades utilizando dos comodines>: % (que se comporta de forma similar al (*) en las bsquedas de Windows) y _ (de comportamiento similar a (?) en Windows). Aqu tienes algunas de sus posibilidades:
Cdigo Ver fuente ejemplo Ver Ver Ver Ver Probar Probar Probar Probar
Sintaxis WHERE campoLIKE '%cadena%' WHERE campoLIKE 'cadena%' WHERE campoLIKE '%cadena' WHERE campoLIKE '_cadena%'
Descripcin Selecciona todos los registros que contengan la cadena en el campo indicado sea cual fuere su posicin Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente al principio del campo Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente al final del campo Selecciona todos los registros en los que el primer caracter del campo puede ser cualquiera pero los siguientes han de serexactamente los indicados en cadena pudiendo ir seguidos de cualesquiera otros caracteres
El comodn (_) puede ir tanto al principio como al final y puede repetirse tantas veces como sea necesario. Por tanto sera correctoLIKE '___es%' y tambin LIKE 'a___es%' as como: LIKE '%a___es'. La clasula WHERE aun tiene ms opciones. Acepta mltiples condiciones vinculadas por los operadores lgicos AND, OR, NOT o sus sintaxis equivalentes: &&, || y !. El comportamiento de estos operadores es idntico al descrito para sus homnimos de PHP en esta pgina
Recuento de resultados
PHP dispone de dos funciones que permiten conocer el nmero de registros de la tabla afectados por una sentencia MySQL. mysql_num_rows ($c ) Esta funcin devuelve un valor numrico que recoge el nmero de registros que cumplen las condiciones establecidas en unaconsulta. Slo es vlido para sentencia tipo SELECT mysql_affected_rows($c ) En este caso la funcin devuelve tambin el nmero de registros afectados, pero slo en el caso de que la sentencia MySQL haya producido modificaciones en los contenidos de la tabla. Es decir, slo recoge resultados de sentencias que: aaden, modifican o borranregistros. mysql_result($resultado,num, campo) Esta funcin PHP permite obtener un solo campo de uno solo de los registros obtenidos como resultado de una consulta MySQL. El parmetro $resultado es la variable que recoge el resultado obtenido de la ejecucin de mysql_query de forma idntica a como lo hacamos en otras consultas. El valor num es un nmero entero que indica el nmero de fila de la que queremos extraer el valor contenido en uno de sus campos. El valor campo indica el nmero del campo que tratamos de extraer. Este nmero (la primera posicin siempre es cero) indica el nmero de orden del campo tal como est especificado en la sentencia SELECT. Si en esta sentencia se incluyera * (extraer todos los campos) considerara el orden en el que est creada la estructura de la tabla que los contiene. Este es el cdigo fuente de un ejemplo comentado y este un enlace de prueba del script.
CURRENT_TIMESTAMP() Se comporta de forma similar a CURDATE(). Devuelve la fecha y hora actual del sistema en formato YYYY-MM-DD hh:mm:ss NOW() Es un alias de CURRENT_TIMESTAMP(). Aqu tienes una tabla resumen y algunos ejemplos
Ver cdigo Ver ejemplo Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar
Formato Descripcin %d %e %D %m %c %M %b %y %Y %w %W %W %j %U %u Da del mes en formato de dos dgitos Da del mes en formato de uno dos dgitos Nmero de da seguido del sufijo en ingls Nmero del mes en formato de dos dgitos Nmero del mes en formato de uno o dos dgitos Nombre del mes (en ingls) Nombre del mes abreviado (en ingls) Nmero del ao en formato de dos dgitos Nmero del ao en formato de cuatro dgitos Nmero de da de la semana 0=Domingo ... 6=Sbado Nombre del da de la semana (en ingls) Nombre abreviado del da de la semana (en ingls) Nmero de da del ao en formato de 3 dgitos Nmero de semana del ao considerando el DOMINGO como primer da de la semana (en formato de dos dgitos) Nmero de semana del ao considerando el LUNES como primer da de la semana (en formato de dos dgitos)
Sintaxis
DATE_FORMAT(Nacimiento,'%d') Ver DATE_FORMAT(Nacimiento,'%e') Ver DATE_FORMAT(Nacimiento,'%D') Ver DATE_FORMAT(Nacimiento,'%m') Ver DATE_FORMAT(Nacimiento,'%c') Ver DATE_FORMAT(Nacimiento,'%M') Ver DATE_FORMAT(Nacimiento,'%b') Ver DATE_FORMAT(Nacimiento,'%y') Ver DATE_FORMAT(Nacimiento,'%Y') Ver DATE_FORMAT(Nacimiento,'%w') Ver DATE_FORMAT(Nacimiento,'%W') Ver DATE_FORMAT(Nacimiento,'%W') Ver DATE_FORMAT(Nacimiento,'%j') Ver
La fecha para los ejemplos siguientes la extraemos de una variable del tipo:
$fecha="2005-10-12 14:23:42"
ya que la tabla no contiene campos de fecha que incluyan horas, minutos y segundos %H %k %h %I %i %s %r %T %p Hora con dos dgitos (formato 0 a 24 horas) Hora con uno dos dgitos (formato 0 a 24 horas) Hora con dos dgitos (formato 0 a 12 horas) Hora con uno dos dgitos (formato 0 a 12 horas) Minutos con dos dgitos Segundos con dos dgitos Hora completa (HH:mm:ss) en formato de 12 horas indicando AM PM Hora completa (HH:mm:ss) en formato de 24 horas Aade AM PM dependiendo de la Hora DATE_FORMAT($fecha,'%H') DATE_FORMAT($fecha,'%k') DATE_FORMAT($fecha,'%h') DATE_FORMAT($fecha,'%I') DATE_FORMAT($fecha,'%i') DATE_FORMAT($fecha,'%s') DATE_FORMAT($fecha,'%r') DATE_FORMAT($fecha,'%T') DATE_FORMAT($fecha,'% texto') DATE_FORMAT($fecha,'%p') Ver Probar
Se pueden combinar a voluntad varias opciones utilizando una sintaxis de este tipo: '% Hoy es: %d - %m - %Y % es %W % estamos en el mes de %M % <br>y van transcurridos %j % dias de este ao.<br>Son las %r'
Una primera opcin sera crear tres tablas una para cada tribunal e incluir en ellas todos los datos de cada uno de los individuos. Esa opcin es factible pero no es ni la ms cmoda, ni tampoco es la ms rpida ni la que menos espacio de almacenamiento necesita. No debemos olvidar que una tabla puede tener una enorme cantidad de registros. Una opcin alternativa sera crear tres nuevas tablas que slo contuvieran dos campos cada una. Por ejemplo el campo DNI y el campo Calificacin. Como quiera que el campo DNI ha de contener los mismos valores en las cuatro tablas y adems es un campo nicopodran crearse las nuevas tablas y luego copiar en cada una de ellas todos los DNI de la tabla original. Nos garantizara que no habra errores en los DNI y adems nos garantizara que se incluyeran todos los aspirantes en esas nuevas tablas. Aqu tienes el cdigo fuente de un script que crea esas tres tablas (a las que hemos llamado demodat1, demodat2 y demodat3.
Ver cdigo fuente
en la que, como ves, modificamos ligeramente la sintaxis ya que anteponemos el nombre de la tabla al del campo correspondiente separando ambos nombres por un punto, con lo cual no hay posibilidad de error de identificacin del campo incluso cuando campos de distinta tabla tengan el mismo nombre. Otra innovacin -respecto a los ejemplos anteriores- es que detrs de la clusula FROM escribimos los nombres de todas las tablas que est usando SELECT. A partir de ah se pueden establecer todo tipo de relaciones para las sentencias WHERE, ORDER BY y GROUP BY utilizando para ellocampos de cualquiera de las tablas sin otra particularidad ms que poner cuidado al aludir a los campos utilizando siempre la sintaxisnombre_tabla.nombre_campo. A modo de ejemplo hemos procurado comentarlo lnea a lnea aqu tienes un script PHP que hace una consulta conjunta de las tablasdemo4, demodat1, demodat2 y demodat3 y nos presenta una tabla con los datos personales y las puntuaciones de las tres pruebas as como las suma de puntos de las tres y, adems, ordena los resultados -de mayor a menor- segn la suma de las tres puntuaciones.
Ejecutar consulta Ver cdigo fuente
Cuidado! Hay que tener muy presente que con esta sentencia en la que no aparece WHERE se modificarn TODOS LOS REGISTROS DE LA TABLA y por lo tanto los campos modificados tendrn el mismo valor en todos los registros.
Definir la variable as: $variable ="'valor'" (comillas dobles, comilla simple al principio y comilla simple, comilla doble al final) y poner en la sentencia MySQL el nombre de la variable sin entrecomillar, o Definir la variable PHP as: $variable ="valor" y al escribir el nombre de esa variable en la sentencia MySQL escribirlo entre comillas sencillas, es decir, as: '$variable' No pienses que es caprichoso el orden que hemos puesto en las comillas. Recuerda que al llamar a la sentencia MySQL, el contenido de la sentencia va entre comillas (que por costumbre son comillas dobles, por esa razn todo entrecomillado que vaya dentro de esa sentencia ha de usar comillas simples para evitar un error seguro). De ah que al definir una variable PHP en la forma $variable ="'valor'" las comillas dobles exteriores indican a PHP que se trata de una cadena, por lo que, al pasar la variable a MySQL ste recibir el contenido de la cadena que es, logicamente: 'valor' y en este caso las comillas forman parte del valor, razn por el que no es necesario escribir -en la sentencia MySQL- el nombre de la variable entrecomillado. En este primer ejemplo, hemos incluido una actualizacin de tablas que pondr puntuacin 7 en la primera de las pruebas a todos losaspirantes a astronautas de nuestro ejemplo. Es un caso de actualizacin sin la condicin WHERE y tiene el cdigo comentado.
Ejecutar la modificacin Ver cdigo fuente
La condicin es fundamental en esta opcin y normalmente aludir a un campo ndice (clave principal o nica), de modo que sea un solo registro el que cumpla la condicin. Podra ser el caso, en nuestro ejemplo, del campo DNI que por su unicidad garantizara que la modificacin solamente va a afectar a uno solo de los registros. El ejemplo siguiente nos permitir hacer modificaciones de este tipo en la tabla deomodat2. Observa el cdigo fuente y vers que mediante un simple recurso JavaScript, el script que realiza la modificacin nos reenva al formulario con un mensaje de confirmacin de la modificacin.
Ejecutar la modificaccin Ver cdigo formulario Ver cdigo script
Es opcional e indica a MySQL que espere para realizar la actualizacin a que terminen las consultas del fichero (en el caso de haber alguna en proceso). FROM Tiene carcter obligatorio y debe preceder a la definicin de la tabla en la que se pretende eliminar registros. tabla Es obligatoria e indica el nombre de la tabla en la que pretendemos efectuar el borrado o eliminacin de los registros. WHERE Es un campo opcional y su comportamiento es idntico al sealado en al mencionar el proceso de consultas. LIMIT n La opcin LIMIT es opcional y propia de MySQL. Su finalidad es limitar el tiempo de ejecucin del comando DELETE ya que cuando est activada devuelve el control al potencial cliente despus de borrar n registros, con lo que en procesos de borrados muy largos (ficheros de gran tamao) no obliga a esperar a borrado total para proceder a la consulta de la tabla. Cuando se utiliza esta opcin, la sentencia DELETE debe repetirse hasta que el nmero de registros pendientes de borrado sea inferior al valor de n.
Ten muy presente que con esta sentencia -en la que no aparece WHERE- se BORRARN TODOS LOS REGISTROS DE LA TABLA. Respecto a otras posibles opciones, no difiere en nada de lo indicado en la pgina anterior. Simplemente habra que sustituir en aquellos script UPDATE por DELETE. Borrar un registro no es otra cosa que un caso particular de modificacin.
Hecho este pequeo inciso -creemos que importante y necesario - continuaremos con la referencia al borrado de registros. En este ejemplo, tienes el cdigo fuente de un script que realiza el borrado de un registo mediante un formulario en el que se inserta el DNI tanto en la tabla demo4 como demodat1, demodat2 y demodat3 manteniendo la integridad referencial entre los cuatro ficheros.
Ver cdigo fuente
donde podremos elegir una, varias o todas la tablas y que segn la opciones elegidas nos permite exportar estructuras y/o datos, segn las casillas de verificacin que tengamos marcadas. Adems nos permite elegir el formato en el que queremos guardar la copia en nuestro caso elegiramos SQL y tambin segn est o no activada la casilla de verificacin Enviar visualizar el fichero generado o guardarlo con el nombre que hayamos consignado en la caja de texto Plantilla del nombre del archivo.
Para restaurar datos y/o estructuras desde un fichero de seguridad creado mediante el proceso anterior usaramos la opcin SQL de la primera imagen. A travs de ella accederamos a una pgina cuyo contenido estamos visualizando en esta ltima imagen. Bastara pulsar en examinar, buscar el fichero de seguridad y pulsar contine. MySQL se encargara de restaurar en la base de datos a la que pertenezcan todas las tablas contenidas en esa copia.
Optimizacin de tablas
Cuando se ejecuta la sentencia DELETE -pese a que son eliminados los valores de los camposse conservan las posiciones de los registros borrados, con lo cual no se reduce el tamao de la tabla. Esas posiciones de registro sern utilizadas por MySQL para escribir los registros que se vayan aadiendo despus del proceso de borrado. Para eliminar esos registros vacos y reducir el tamao de una tabla, MySQL dispone de una sentencia que es la siguiente: OPTIMIZE TABLE tabla
Esta sentencia -que debe usarse despus de un proceso de borrado amplio- depura la tabla eliminando los registros inutilizados por el proceso DELETE, con lo que logra una reduccin del tamao de la tabla a su dimensin ptima.
<?php #el nombre de la tabla $base="ejemplos"; #definimos otra variable con el NOMBRE QUE QUEREMOS DAR A LA TABLA $tabla="fotos"; # establecemos la conexin con el servidor $conexion=mysql_connect ("localhost","pepe","pepa"); #Seleccionamos la BASE DE DATOS en la que PRETENDEMOS CREAR LA TABLA mysql_select_db ($base, $conexion);
$crear="CREATE TABLE IF NOT EXISTS $tabla ("; $crear.="num_ident INT(10) unsigned NOT NULL AUTO_INCREMENT,"; $crear.="imagen BLOB NOT NULL, "; $crear.="nombre VARCHAR(255) NOT NULL DEFAULT '',"; $crear.="tamano VARCHAR(15) NOT NULL DEFAULT '',"; $crear.="formato VARCHAR(10) NOT NULL DEFAULT '',"; $crear.="PRIMARY KEY (num_ident))type=MyISAM"; #Creamos la cadena, comprobamos si esa instruccin devuelve # VERDADERO o FALSO # y dependiendo de ellos insertamos el mensaje de exito o fracaso if(mysql_db_query ($base,$crear ,$conexion)) { echo "<h2> Tabla $tabla creada con EXITO </h2><br>"; }else{ echo "<h2> La tabla $tabla NO HA PODIDO CREARSE</h2><br>"; }; # cerramos la conexin... y listo... mysql_close($conexion); ?>
Aqu tiene el cdigo fuente que te permitira crear la tabla fotos e insertar automticamente algunas imgenes de ejemplo.
Ejemplo de transferencia de imagen
Transferencia de la imagen
El formulario para realizar la transferencia de la imagen no tiene particularidades. Es un formulario habitual para transferencia de ficheros. Lo nico reseable sera incluir un campo oculto en el que pudiera especificarse una restriccin en cuanto al tamao mximo permitido para cada imagen y que debe estar acorde con el tipo de campo utilizado en la tabla.
<FORM ENCTYPE="multipart/form-data" ACTION="ejemplo211.php" METHOD="post"> <INPUT type="hidden" name="lim_tamano" value="65000"> <p><b>Selecciona la imagen a transferir<b><br> <INPUT type="file" name="foto"><br> <p><b>Ttulo la imagen<b><br> <INPUT type="text" name="titulo"><br></p> <p><INPUT type="submit" name="enviar" value="Aceptar"></p> </FORM>
Ejemplo de transferencia de imagen
$lim_tamano= $_POST['lim_tamano']; $foto_titulo= $_POST['titulo']; /* limitamos los formatos de imagen admitidos a: png que segun del navegador que ulicemos puede ser: en IE image/x-png en Firefox y Mozilla image/png jpg que puede tener como tipo en IE image/pjpeg en Firefox y Mozilla image/jpeg gif que tiene como tipo image/gif en todos los navegadores Mira los comentarios al margen sobre la variable $extensin */ if ($foto_type=="image/x-png" OR $foto_type=="image/png"){ $extension="image/png"; } if ($foto_type=="image/pjpeg" OR $foto_type=="image/jpeg"){ $extension="image/jpeg"; } if ($foto_type=="image/gif" OR $foto_type=="image/gif"){ $extension="image/gif"; } # condicionamos la insercin a que la foto tenga nombre, # un tamao distinto de cero y menor de lmite establecido # en el formulario y que la variable extensin sea no nula if ($foto_name != "" AND $foto_size != 0 AND $foto_titulo !='' AND $foto_size<=$lim_tamano AND $extension !=''){ /*reconversion de la imagen para meter en la tabla abrimos el fichero temporal en modo lectura "r" binaria"b"*/ $f1= fopen($foto_temporal,"rb"); #leemos el fichero completo limitando # la lectura al tamao de fichero $foto_reconvertida = fread($f1, $foto_size); #anteponemos \ a las comillas que pudiera contener el fichero # para evitar que sean interpretadas como final de cadena $foto_reconvertida=addslashes($foto_reconvertida); # abrimos la base de datos y escribimos las intrucciones de insercin # en el campo BLOB insertaremos la foto_reconvertida $base="ejemplos"; $tabla="fotos"; $conexion=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $conexion); $meter="INSERT INTO ".$tabla; $meter .=" (num_ident, imagen, nombre, tamano, formato) "; $meter .=" VALUES('','$foto_reconvertida','$foto_titulo',"; $meter .= "$foto_size, '$extension')"; if (@mysql_query($meter,$conexion)){ print "Foto guardada en la tabla"; }else{ print "Ha habido un error al guardar la foto"; } }else{ echo "<h2>No ha podido transferirse el fichero</h2>"; } mysql_close(); ?>
Hay otro aspecto a tener en cuenta. Esa discriminacin de tipos se plantea nicamente cuando Apache recibe una transferencia. Cuando se visualiza un contenido las cabeceras tipo de contenido (header("content-type: xx")) pueden ser las mismas para todos los navegadores. Esa es la razn por la que a la hora de incluir el formato en la tabla utilizamos image/jpg, image/gif o image/png.
La informacin recibida a travs del formulario requiere un ligero retoque antes de incluirla en le campo BLOB de la tabla. Esa reconversin requiere abrir la imagen en modo binario (rb) -parece que solo en el caso de Windows leer el fichero completo y aadirle \ antes de las comillas mediante addslashes. Una vez hecho el retoque ya puede guardarse sin ms problema.
Visualizacin de imgenes
La lectura de una imagen utiliza solo dos instrucciones. Incluir la cabecera Header en el que se indica el tipo de contenido (el famoso nombre MIME de la imagen) y luego imprimir el contenido del campo. Pero (por aquello de que header debe ir incluida en el script antes que cualquier otra salida) si pretendemos incluir en una pgina algo ms que una imagen tendremos que invocar esas dos funciones, de forma independiente, para cada una de ellas. Por esa razn, en el ejemplo que tienes al margen, al desarrollar el ejemplo que permite visualizar todas las imgenes de la tabla hemos tenido que incluir un script que va leyendo la tabla que contiene las imgenes para extraer los campos informativos y a la hora de ver la imagen hemos de recurrir a la misma tcnica que se utilizaba para ver las imgenes dinmicas. Es decir, poner una etiqueta de imagen de las de HTML pero -en vez de escribir el nombre de la imagen- poniendo incluyendo como nombre el del script que las visualiza y pasndole elnmero (valor del campo autoincremental) de la imagen que pretend visualizar. Script para leer imgenes de la base datos
<? $numero=$_REQUEST['n']; $base="ejemplos"; $tabla="fotos"; $conexion=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $conexion); $sacar = "SELECT * FROM ".$tabla." WHERE (num_ident=$numero)" ; $resultado = mysql_query($sacar,$conexion); while ($registro = mysql_fetch_array($resultado)){ $tipo_foto=$registro['formato']; header("Content-type: $tipo_foto"); echo $registro['imagen']; } mysql_close(); ?>
Ver imgenes guardadas
<html>
<head> <!-- al margen te comentamos la razn por la que --> <!-- se incluyen estas lneas en rojo --> <!--[if IE ]> <script type="text/javascript" src="pngfix.js"></script> <![endif]--> </head> <body> <? $base="ejemplos"; $tabla="fotos"; $conexion=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $conexion); $sacar = "SELECT * FROM ".$tabla; $resultado = mysql_query($sacar,$conexion); while ($registro = mysql_fetch_array($resultado)){ print "<center>Titulo de la imagen: ".$registro['nombre']."<br>"; /* la inclusin de este condicional obedece a los problemas que plantea la visualizacin de las transparencias de las imgenes png en Internet Explorer. Al margen justificamos las razones de su inclusin */ if($registro['formato']=="image/png"){ print "<img src='ver_foto.php?n=".$registro['num_ident']."&v=png'><br>"; }else{ print "<img src='ver_foto.php?n=".$registro['num_ident']."'><br>"; } print "Tamao de la imagen: ".$registro['tamano']." bytes </center>"; } mysql_close(); ?> </body> </html>
<?php $base="ejemplos"; $tabla="demoinno"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); $crear="CREATE TABLE $tabla ("; $crear.="Contador TINYINT(8) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,"; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, ";
$crear.="Apellido2 VARCHAR (15) not null, "; $crear.="Nacimiento DATE DEFAULT '1970-12-21', "; $crear.="Hora TIME DEFAULT '00:00:00', "; $crear.="Sexo Enum('M','F') DEFAULT 'M' not null, "; $crear.="Fumador CHAR(0) , "; $crear.="Idiomas SET(' Castellano',' Francs','Ingls', ' Alemn',' Blgaro',' Chino'), "; $crear.=" PRIMARY KEY(DNI), "; $crear.=" UNIQUE auto (Contador)"; $crear.=")"; # esta es la nica diferencia con el proceso de # creacin de tablas MyISAM $crear.=" Type=InnoDB"; if(mysql_query ($crear ,$c)) { echo "<h2> Tabla $tabla creada con EXITO </h2><br>"; }else{ echo "<h2> La tabla $tabla NO HA PODIDO CREARSE "; # echo mysql_error ($c)."<br>"; $numerror=mysql_errno ($c); if ($numerror==1050){echo "porque YA EXISTE</h2>";} }; mysql_close($c); ?>
Ver cdigo fuente
Cuidado! Bajo Windows, al crear una base de datos o tabla InnoDB el nombre de la misma aparecer en minsculas independientemente de la sintaxis que hayamos utilizado en su creacin. Para prever posibles conflictos al ejecutar los scripts en diferentes plataformas utilizaremos minsculas para los nombres de tablas.
Una vez creadas, las tablas InnoDB se comportan a efectos de uso exactamente igual que las que hemos venido utilizando en las pginas anteriores. No es preciso hacer ningn tipo de modificacin en la sintaxis. Por tanto, es totalmente vlido todo lo ya comentado respecto a: altas, modificaciones, consultas y bajas.
Las transacciones
Uno de los riesgos que se plantean en la gestin de bases de datos es que pueda producirse una interrupcin del proceso mientras se est actualizando una o varias tablas. Pongamos como ejemplo el cobro de nuestra nmina. Son necesarias dos anotaciones simultneas: El cargo en la cuenta del organismo pagador y el abono en nuestra cuenta bancaria. Si se interrumpiera fortuitamente el proceso en el intermedio de las dos operaciones podra darse la circunstancia de que apareciera registrado el pago sin que se llegaran a anotar los haberes en nuestra cuenta. Las transacciones evitan este tipo de situaciones ya que los datos se registran de manera provisional y no se consolidan hasta que una instruccin confirme que esas anotaciones tienen carcter definitivo. Para ello, MySQL dispone de tres sentencias: BEGIN, COMMIT yROLLBACK.
mysql_query("ROLLBACK",$conexion) Mediante esta sentencia advertimos a MySQL que finaliza la transaccin pero que no debe hacerse efectiva ninguna de las modificaciones incluidas en ella. mysql_query("COMMIT",$conexion) Esta sentencia advierte a MySQL que ha finalizado la transaccin y que S debe hacer efectivos todos los cambios incluidos en ella.
('222222','Genoveva','Zarabozo','Zitrn','1964-01-14', 'F','16:18:20',NULL,2)",$conexion); if (mysql_errno($conexion)==0){ echo "Registro AADIDO"; }else{ if (mysql_errno($conexion)==1062){ echo "No ha podido aadirse el registro <br>"; echo "Ya existe un registro con este DNI"; }else{ $numerror=mysql_errno($conexion); $descrerror=mysql_error($conexion); echo "Se ha producido un error n $numerror"; echo "<br>que corresponde a: $descrerror"; } } # indicamos el final de la transaccin, en este caso con COMMIT # por lo tanto el registro con DNI 222222 si ser insertado en la tabla mysql_query("COMMIT",$conexion); # leamos el contenido de la tabla para ver el resultado $resultado= mysql_query("SELECT * FROM $tabla" ,$conexion); print "<br>Lectura de la tabla depus del commit<br>"; while ($registro = mysql_fetch_row($resultado)){ foreach($registro as $clave){ echo $clave,"<br>"; } } mysql_close(); ?>
La integridad referencial
Elementos necesarios para la integridad referencial
La integridad referencial ha de establecerse siempre entre dos tablas. Una de ellas ha de comportarse como tabla principal (suele llamarse tabla padre y la otra sera la tabla vinculada tabla hijo. Es imprescindible: Que la tabla principal tenga un ndice primario (PRIMARY KEY) Que la tabla vinculada tenga un ndice (no es necesario que sea ni nico ni primario) asociado a campos de tipo idntico a los que se usen para ndice de la tabla principal. Si observas el cdigo fuente del ejemplo que tienes a la derecha podrs observar que utilizamos el nmero del DNI (nico para alumno) como elemento de vinculacin de la tabla de datos personales con la que incluye las direcciones.
FOREIGN KEY (campo de vinculacion) REFERENCES nombre_de la tabla principal (Indice primario de la tabla principal) ) Type=InnoDB donde el campo de vinculacion ha de ser un ndice (no es necesario que sea PRIMARY KEY ni UNIQUE) y donde Indice primario de la tabla principal ha de ser un ndice primario (PRIMARY KEY) de la tabla principal. Debe haber plena coincidencia (tanto en tipos como contenidos) entre ambos ndices.
<?php $base="ejemplos"; $tabla1="principal"; $tabla2="vinculada"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); # creacin de la tabla principal type InnoDB $crear="CREATE TABLE IF NOT EXISTS $tabla1 ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; # el indice primario es imprescindible. Recuerda que debe # estar definido sobre campos NO NULOS $crear.=" PRIMARY KEY(DNI) "; $crear.=")"; $crear.=" Type=InnoDB"; # creamos la tabla principal comprobando el resultado if(@mysql_query ($crear ,$c)){ print "La tabla ".$tabla1." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla1." ha habido un error<br>"; } # crearemos la tabla vinculada $crear="CREATE TABLE IF NOT EXISTS $tabla2 ("; $crear.="IDENTIDAD CHAR(8) NOT NULL, "; $crear.="calle VARCHAR (20), "; $crear.="poblacion VARCHAR (20), "; $crear.="distrito VARCHAR(5), "; # creamos el ndice (lo llamamos asociador) para la vinculacin # en este caso no ser ni primario ni nico # Observa que el campo IDENTIDAD de esta tabla CHAR(8) # es idntico al campo DNI de la tabla principal $crear.=" KEY asociador(IDENTIDAD), "; #establecemos la vinculacin de ambos ndices $crear.=" FOREIGN KEY (IDENTIDAD) REFERENCES $tabla1(DNI) "; $crear.=") TYPE = INNODB"; # creamos (y comprobamos la creacin) la tabla vinculada if(@mysql_query ($crear ,$c)){ print "La tabla ".$tabla2." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla2." ha habido un error<br>"; } mysql_close(); ?>
Modificacin de estructuras
La modificacin de estructuras en tablas vinculadas puede hacerse de forma idntica a la estudiada para los casos generales de MySQL siempre que esas modificaciones no afecten a los campos mediante los que se establecen las vinculaciones entre tablas. Aqu tienes un ejemplo en se borran y aaden campos en ambas tablas. Como puedes ver la sintaxis es exactamente la misma que utilizamos en temas anteriores.
<?php $base="ejemplos"; $tabla="principal"; $tabla1="vinculada"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); if(mysql_query("ALTER print "Sea ha } if(mysql_query("ALTER print "Sea ha } if(mysql_query("ALTER print "Sea ha } if(mysql_query("ALTER print "Sea ha } mysql_close(); ?> TABLE $tabla ADD Segundo_Apellido VARCHAR(40)",$c)){ creado el nuevo campo en ".$tabla."<br>"; TABLE $tabla DROP Apellido2",$c)){ borrado el campo Apellido 2 en ".$tabla."<br>"; TABLE $tabla1 ADD DP VARCHAR(5)",$c)){ creado el nuevo campo en ".$tabla1."<br>"; TABLE $tabla1 DROP distrito",$c)){ borrado el campo distrito en ".$tabla1."<br>";
<?php $base="ejemplos"; $tabla="vinculada"; $tabla1="principal"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); $resultado=mysql_query( "SHOW CREATE TABLE $tabla",$c); $v=mysql_fetch_array($resultado); # extreamos de Create Table la cadena que empiza por CONSTRAINT # y que acaba por FOREING KEY lo guardamos en el array $coin preg_match ('/CONSTRAINT.*FOREIGN KEY/', $v['Create Table'], $coin);
# extraemos el parametro quitando el CONSTRAINT que lleva delante # y el FOREIGN KEY que lleva al final $para=str_replace("FOREIGN KEY",'',str_replace("CONSTRAINT",'',$coin[0])); print "El valor de CONSTRAINT es: ".$para."<br>"; # eliminamos el vinculo con la clave externa incluyendo en la sentancia # el valor del parametro obtenido el proceso anterior if(mysql_query("ALTER TABLE $tabla DROP FOREIGN KEY $para",$c)){ print "Se ha realizado con xito el borrado del vnculo<br>"; } # aadimos el nuevo vnculo (en este caso rehacemos el anterior # pero el proceso es idntico) if(mysql_query("ALTER TABLE $tabla ADD CONSTRAINT $para FOREIGN KEY(IDENTIDAD) REFERENCES $tabla1(DNI)",$c)){ print "Se ha reestablecido con xito vnculo<br>"; } mysql_close(); ?>
La funcin preg_match
En el ejemplo hemos utilizamos esta la funcin (relacionada con el uso de expresiones regulares): preg_match( patron, cadena, coincidencias ) dnde patron es un patrn de bsqueda, cad es la cadena que la han de realizarse las bsquedas y coin es un array que recoge todas las coincidencias encontradas en la cadena. El patrn de bsqueda que hemos utilizado en el ejemplo /CONSTRAINT.*FOREIGN KEY/ debe interpretarse de la siguiente forma. Los caracteres / indican el comienzo y el final del patrn, el . indica que entre CONSTRAIT y FOREING se permite cualquier carcter y, adems,* indica que ese caracter cualquiera puede repetirse cero o ms veces.
y ahora ya podremos ejecutar -sin errores- el script que inserta datos en la tabla vinculada. Podremos ejecutar aquel script tantas veces como queramos ya que -el campo IDENTIDAD est definido como KEY y por tanto permite duplicados- no hemos establecido la condicin de ndice PRIMARIO UNICO.
Sin tratamos de modificar un registro de la tabla principal y la modificacin afecta al ndice que realiza la asociacin con la tabla (o tablas) vinculadas se producira -por las mismas razones y en las mismas circunstancias- un error 1451 que corresponde a: Cannot delete or update a parent row: a foreign key constraint fails (`ejemplos`.`vinculada`, CONSTRAINT `vinculada_ibfk_1` FOREIGN KEY (`IDENTIDAD`) REFERENCES `principal` (`DNI`)) que impedira la modificacin.
Modificar DNI en tabla principal Ver script
Si -al tratar de borrar o modificar un registro de la tabla principal no existieran en la tabla (o tablas vinculadas) registros asociados con l, el proceso de modificacin se realizara sin ningn problema y sin dar ningn mensaje de error o advertencia.
Cuidado! El uso de la opcin SET NULL requiere que el campo indicado en FOREIGN KEY est permita valores nulos. Si est definido con flag NOT NULL (como ocurre en los ejemplos que tienes al margen) dara un mensaje de error.
Cuidado! Al incluir ON DELETE y ON UPTADE (si se incluyen ambas) han de hacerse por este mismo orden. Si se cambiara este orden dara un mensaje de error y no se ejecutaran.
Automatizacin de procesos
Creamos dos tablas idnticas a las anteriores incluyendo algunos datos en ellas.
<?php $base="ejemplos"; $tabla1="principal1"; $tabla2="vinculada1"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); # creacin de la tabla principal type InnoDB $crear="CREATE TABLE IF NOT EXISTS $tabla1 ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; $crear.=" PRIMARY KEY(DNI) "; $crear.=")"; $crear.=" Type=InnoDB"; # creamos la tabla principal comprobando el resultado if(@mysql_query ($crear ,$c)){ print "La tabla ".$tabla1." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla1." ha habido un error<br>"; } # crearemos la tabla vinculada $crear="CREATE TABLE IF NOT EXISTS $tabla2 ("; $crear.="IDENTIDAD CHAR(8) NOT NULL, "; $crear.="calle VARCHAR (20), "; $crear.="poblacion VARCHAR (20), "; $crear.="distrito VARCHAR(5), "; #creamos la tabla vinculada las opciones de DELETE y UPDATE $crear.=" KEY asociador(IDENTIDAD), "; #establecemos la vinculacin de ambos ndices $crear.=" FOREIGN KEY (IDENTIDAD) REFERENCES $tabla1(DNI) "; $crear.=" ON DELETE CASCADE "; $crear.=" ON UPDATE CASCADE "; $crear.=") TYPE = INNODB"; # creamos (y comprobamos la creacin) la tabla vinculada if(@mysql_query ($crear ,$c)){ print "La tabla ".$tabla2." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla2." ha habido un error<br>"; } # aadimos registros a la tabla principa1 mysql_query("INSERT $tabla1 (DNI,Nombre,Apellido1,Apellido2) VALUES ('111111','Robustiano','Iglesias','Prez')",$c); mysql_query("INSERT $tabla1 (DNI,Nombre,Apellido1,Apellido2) VALUES ('222222','Ambrosio','Morales','Gmez')",$c); # aadimos registros a la tabla vinculada1 mysql_query("INSERT $tabla2 (IDENTIDAD,calle,poblacion,distrito) VALUES ('111111','Calle Asturias,3','Oviedo','33001')",$c); mysql_query("INSERT $tabla2 (IDENTIDAD,calle,poblacion,distrito) VALUES ('111111','Calle Palencia,3','Logroo','78541')",$c); mysql_query("INSERT $tabla2 (IDENTIDAD,calle,poblacion,distrito)
Crearemos una primera tabla (alumnos) que va a contener datos personales de un grupo de personas. Para evitar duplicar un mismo alumno y alumnos sin DNI, vamos a utilizar como ndice primario (PRIMARY KEY) el campo DNI (que es nico para cada persona). La condicin de que el campo DNI sea PRIMARY KEY nos obliga a definirlo con el flag NOT NULL, dado que esta es una condicin necesaria para la definicin de ndices primarios. Crearemos una segunda tabla (domicilios) con los domicilios de cada uno de los alumnos, identificndolos tambin por su DNI. Para evitar que un mismo alumno pueda tener dos domicilios asignamos a al campo DNI de esta tabla la condicin de ndice nico (UNIQUE). El ndice UNIQUE podramos haberlo creado tambin como PRIMARY KEY ya que la nica diferencia de comportamiento entre ambos es el hecho que aquel admitira valores NULOS pero, dado que debemos evitar domicilios sin alumnos, insertaremos el flag NOT NULL en este campo. El hecho de utilizar dos tablas no tiene otro sentido que la ejemplificacin ya que lo habitual sera que todos los datos estuvieran en una misma tabla. Vincularemos ambas tablas de modo que no puedan crearse direcciones de alumnos inexistentes y les pondremos la opcin de actualizacin y borrado en cascada. De esta forma las acciones en la tabla de alumno se reflejaran automticamente en la tabla de domicilios. La tercera de las tablas (evaluaciones) tiene como finalidad definir las distintas evaluaciones que puede realizarse a cada alumno. Tendr dos campos. Uno descriptivo (el nombre de la evaluacin) y otro identificativo (no nulo y nico) que ser tratado como PRIMARY KEY para evitar duplicidades y porque, adems, va a ser utilizado como clave fornea en la tabla notas. La tabla notas va a tener tres campos: DNI, n de evaluacin y calificacin. Estableceremos restricciones para evitar que: Podamos calificar a un alumno inexistente. Podamos calificar una evaluacin no incluida entre las previstas. Podamos poner a cada alumno ms de una calificacin por evaluacin. Creando una ndice primario formado por los campos DNI y evaluacin evitaremos la ltima de las situaciones y aadiendo una vinculacin con las tablas alumnos y evaluaciones estaremos en condiciones de evitar las dos primeras.
<?php $base="ejemplos"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); ############################################### # Creacin de la tabla nombres con indice primario DNI # tabla de nombres con ndice primario en DNI ############################################### $crear="CREATE TABLE IF NOT EXISTS alumnos ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; $crear.=" PRIMARY KEY(DNI) "; $crear.=")"; $crear.=" Type=InnoDB"; if(mysql_query ($crear ,$c)){ print "tabla <b>nombres</b> creada<BR>"; }else{ print "ha habido un error al crear la tabla <b>alumnos</b><BR>"; } ###############################################
# Creacin de la tabla direcciones # tabla de nombres con ndice nico en DNI # para evitar dos direcciones al mismo alumno # y clave fornea nombres(DNI) # para evitar direcciones no asociadas a un alumno # concreto. Se activa la opcin de actualizar # en cascada y de borrar en cascada ############################################### $crear="CREATE TABLE IF NOT EXISTS domicilios ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="calle VARCHAR (20), "; $crear.="poblacion VARCHAR (20), "; $crear.="distrito VARCHAR(5), "; $crear.=" UNIQUE identidad (DNI), "; $crear.="FOREIGN KEY (DNI) REFERENCES alumnos(DNI) "; $crear.="ON DELETE CASCADE "; $crear.="ON UPDATE CASCADE "; $crear.=") TYPE = INNODB"; if(mysql_query ($crear ,$c)){ print "tabla <b>domicilios</b> creada<br>"; }else{ print "ha habido un error al crear la tabla <b>domicilios</b><BR>"; } ############################################### # Creacin de la tabla nombres con indice primario EVALUACIONES # tabla de nombres con ndice primario en NUMERO ############################################### $crear="CREATE TABLE IF NOT EXISTS evaluaciones ("; $crear.="NUMERO CHAR(1) NOT NULL, "; $crear.="nombre_evaluacion VARCHAR (20) NOT NULL, "; $crear.=" PRIMARY KEY(NUMERO)"; $crear.=")"; $crear.=" Type=InnoDB"; if(mysql_query ($crear ,$c)){ print "tabla <b>evaluaciones</b> creada<BR>"; }else{ print "ha habido un error al crear la tabla <b>evaluaciones</b><BR>"; } ############################################### # Creacin de la tabla notas # indice UNICO para los campos DNI y evaluacion # con ello se impide calificar dos veces al mismo # alumno en la misma evaluacion # claves forneas (DOS) # el DNI de nombres para evitar calificar a alumnos inexistentes # el NUMERO de la tabla evaluaciones para evitar calificar # DOS VECES en una evaluacin a un alumno ############################################### $crear="CREATE TABLE IF NOT EXISTS notas ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="evaluacion CHAR (1) NOT NULL, "; $crear.="calificacion TINYINT (2), "; /* observa que este indice primario est formado por dos campos (DNI y evalucion) y que, como siempre en el caso de PRIMARY KEY ambos son de tipo NOT NULL */ $crear.=" PRIMARY KEY vemaos(DNI,evaluacion), "; /* Fijate en la secuencia siguiente: 1.- Creamos el ndice 2.- Establecemos la clave fornea 3.- Establecemo las condiciones ON DELETE 4.- Establecemos las condiciones ON UPDTE Es muy importe mantener esta secuencia para evitar
errores MySQL */ $crear.=" INDEX identico (DNI), "; $crear.="FOREIGN KEY (DNI) REFERENCES alumnos(DNI) "; $crear.="ON DELETE CASCADE "; $crear.="ON UPDATE CASCADE,"; /* Esta tabla tiene dos claves forneas asociadas a dos tablas la anterior definida sobre alumnos como tabla principal y esta que incluimos a continuacin asociada con evaluaciones Como ves repetimos la secuencia descrita anteriormente Es importante establecer estas definiciones de una en una (tal como ves en este ejemplo) y seguir la secuencia comentada anteriormente */ $crear.=" INDEX evalua (evaluacion),"; $crear.="FOREIGN KEY (evaluacion) REFERENCES evaluaciones(NUMERO) "; $crear.="ON DELETE CASCADE "; $crear.="ON UPDATE CASCADE"; $crear.=") TYPE = INNODB"; if(mysql_query ($crear ,$c)){ print "tabla <b>notas</b> creada <BR>"; }else{ print "ha habido un error al crear la tabla <b>notas</b><BR>"; echo mysql_error ($c)."<br>"; echo mysql_errno ($c); } mysql_close(); ?> Cuidado! Como puedes observar en la imagen, al definir la estructura de las tablas es muy importante prestar atencin a que los campos vinculados sean del mismo tipo y dimensin. Observa tambin que los campos de referencia de los vnculos que se establecen (en las tablas primarias) tienen que ser definidos como PRIMARY KEY y que, por tanto, han de establecerse como no nulos (NOT NULL).
Importacin de ficheros
MySQL permite insertar en sus tablas los contenidos de ficheros de texto. Para ello utiliza la sentencia que tienes al margen y que detallaremos a continuacin. LOAD DATA INFILE Es un contenido obligatorio que defina la opcin de insertar datos desde un fichero externo. nombre del fichero Se incluye inmediatamente despus de la anterior, es obligatorio y debe contener (entre comillas) la ruta, el nombre y la extensin del fichero que contiene los datos a insertar. [REPLACE|IGNORE] Es opcional. Si se omite se producir un mensaje de error si el fichero contiene valores iguales a los contenidos en los campos de la tabla que no admiten duplicados. Con la opcin REPLACE sustituira los valores existentes en la tabla y con la opcin IGNORE INTO TABLE nombre Tiene carcter obligatorio y debe incluir como nombre el de la tabla a la que se pretenden agregar los registros. FIELDS Tiene carcter OPCIONAL y permite incluir especificaciones sobre cuales son los caracteres delimitadores de campos y los que indican el final del campo. Si se omite FIELDS no podrn incluirse los ENCLOSED BY ni TERMINATED BY de campo.
ENCLOSED BY Permite espeficar (encerrados entre comillas) los caracteres delimitadores de los campos. Estos caracteres debern encontrarse en el fichero original al principio y al final de los contenidos de cada uno de los campos (por ejemplo, si el carcter fueran comillas los campos deberan aparecer as en el fichero a importar algo como esto: "32.45"). Si se omite esta especificacin (o se omite FIELDS) se entender que los campos no tienen caracteres delimitadores. Cuando se incluyen como delimitadores de campo las comillas (dobles o sencillas) es necesario utilizar una sintaxis como esta: '\"' '\'' de forma que no quepa la ambigedad de si se trata de un carcter o de las comillas de cierre de una cadena previamente abierta. TERMINATED BY Se comporta de forma similar al anterior. Permite qu caracteres son usados en el fichero original como separadores de campos (indicador de final de campo). Si se omite, se interpretar con tal el carcter tabulador (\t). El uso de esta opcin no requiere que se especifique previamente ENCLOSED BY pero si necesita que se haya incluidoFIELDS. LINES Si el fichero de datos contiene caracteres (distintos de los valores por defecto) para sealar el comienzo de un registro, el final del mismo o ambos, debe incluirse este parmetro y, despus de l, las especificaciones de esos valores correspondientes a: STARTING BY Permite especificar una carcter como indicador de comienzo de un registro. Si se omite o se especifica como '' se interpretar que no hay ningn carcter que seale en comienzo de lnea. TERMINATED BY Es el indicador del final de un registro. Si se omite ser considerado como un salto de lnea (\n). Insercin de datos en tablas MySQL permite importar ficheros externos utilizando la siguiente sintaxis: LOAD DATA INFILE "nombre del fichero' [REPLACE | IGNORE] INTO TABLE nombre de la tabla FIELDS TERMINATED BY 'indicador de final de campo' ENCLOSED BY 'caracteres delimitadores de campos' LINES STARTING BY 'caracteres indicadores de comienzo de registro' TERMINATED BY 'caracteres indicadores del final de registro' En este ejemplo puedes ver un caso prctico de insercin de datos en las tablas creadas anteriormente.
<?php $base="ejemplos"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); /* evitamos los conflictos de los saltos de linea segun el sistema operativo */ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { $salto_linea="'\r\n'"; }else{ $salto_linea="'\n'"; } /* hemos creado un fichero de texto (datos_alumnos.txt) que contiene datos de algunos alumnos. Los diferentes campos estn entre comillas y separados unos de otros mediante un punto y coma. Cada uno de los registros comienza por un asterios y los registros estn separados por un salto de lnea (\r\n) en Windows o (\n) en Linux. Por esa razn de compatibilidad de sistemas hemos incluido estos valores en una variable $Salto_linea cuyo contenido difiere sengun sistema operativo que est ejecutando este script Incluimos ests especificaciones en la sentencia de insercin */ $query="LOAD DATA INFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/datos_alumnos.txt'."'"; $query.= " REPLACE INTO TABLE alumnos"; $query.= " FIELDS ENCLOSED BY '\"' TERMINATED BY ';' "; $query.=" LINES STARTING BY '*' TERMINATED BY $salto_linea "; if(mysql_query($query,$c)){ print "Datos de alumnos cargados<br>";
}else{ print mysql_error ($c)."<br>".mysql_errno ($c); } /* Para esta tabla usaremos el fichero datos_evaluaciones.txt Los diferentes campos estn entre comillas y separados unos de otros mediante una coma. Cada uno de los registros comienza por un espacio y los registros estn separados por un salto de lnea (\r\n) en Windows o (\n) en Linux. Por esa razn de compatibilidad de sistemas hemos incluido estos valores en una variable $Salto_linea cuyo contenido difiere sengun sistema operativo que est ejecutando este script Incluimos ests especificaciones en la sentencia de insercin */ $query="LOAD DATA INFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/datos_evaluaciones.txt'."'"; $query.= " REPLACE INTO TABLE evaluaciones"; $query.= " FIELDS ENCLOSED BY '\'' TERMINATED BY ',' "; $query.=" LINES STARTING BY ' ' TERMINATED BY $salto_linea "; if(mysql_query($query,$c)){ print "Datos de evaluaciones cargados<br>"; }else{ print mysql_error ($c)."<br>".mysql_errno ($c); } /* En este caso no incluimos especificacin alguna. Bajo este suspuesto MySQL interpreta los valores por defecto que son: los campos no van encerrados, las lneas no tienen ningn carcter indicador de comienzo, los campos estn separados mediante tabulaciones (carcter de escape \t) y el final de lnea est sealado por un caracter de nueva lnea (\n) */ $query="LOAD DATA INFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/datos_notas.txt'."'"; $query.= " IGNORE INTO TABLE notas"; if(mysql_query($query,$c)){ print "Datos de notas cargados<br>"; }else{ print mysql_error ($c)."<br>".mysql_errno ($c); } /* Se comporta como los casos anteriores con distincos caracteres para los diferentes eventos, tal como puedes ver en el cdigo */ $query="LOAD DATA INFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/datos_domicilios.txt'."'"; $query.= " IGNORE INTO TABLE domicilios"; $query.= " FIELDS ENCLOSED BY '|' TERMINATED BY '*' "; $query.=" LINES STARTING BY '#' TERMINATED BY '}' "; if(mysql_query($query,$c)){ print "Datos de domicilios cargados "; }else{ print mysql_error ($c)."<br>".mysql_errno ($c); } mysql_close(); ?>
Consultar tablas
Cuidado! Al importar ficheros habr de utilizarse el mismo formato con el que fueron creados tanto FIELDS como LINES.
Exportacin de ficheros
Se comporta de forma similar al supuesto anterior. Utiliza la sintaxis siguiente: SELECT * INTO OUTFILE Inicia la consulta de los campos especificados despus de SELECT (si se indica * realiza la consulta sobre todos los campos y por el
orden en el que fue creada la tabla) y redirige la salida a un fichero. nombre del fichero Es la ruta, nombre y extensin del fichero en el que sern almacenados los resultados de la consulta. FIELDS ENCLOSED BY TERMINATED BY LINES STARTING BY TERMINATED BY Igual que ocurra en el caso de importacin de datos, estos parmetros son opcionales. Si no se especifican se incluirn los valores por defecto. FROM nombre Su inclusin tiene carcter obligatorio. El valor de nombre ha de ser el de la tabla sobre la que se realiza la consulta. Guardar datos en ficheros MySQL permite los contenidos de sus tablas a ficheros de texto. Para ello utiliza la siguiente sintaxis: SELECT * INTO OUTFILE "nombre del fichero' FIELDS TERMINATED BY 'indicador de final de campo' ENCLOSED BY 'caracteres delimitadores de campos' LINES STARTING BY 'caracteres indicadores de comienzo de registro' TERMINATED BY 'caracteres indicadores del final de registro' FROM nombre de la tabla
<?php $base="ejemplos"; $c=mysql_connect ("localhost","pepe","pepa"); mysql_select_db ($base, $c); $query="SELECT * INTO OUTFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/alumnos.txt'."'"; $query.= " FIELDS ENCLOSED BY '\"' TERMINATED BY ';' "; $query.=" LINES STARTING BY '*' TERMINATED BY '\r\n' "; $query.=" FROM alumnos"; if(mysql_query($query,$c)){ print "fichero alumnos.txt creado<br>"; }else{ print mysql_error ($c)."<br>". mysql_errno ($c); } $query="SELECT * INTO OUTFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/domicilios.txt'."'"; $query.= " FIELDS ENCLOSED BY '|' TERMINATED BY '*;' "; $query.=" LINES STARTING BY '#' TERMINATED BY '}' "; $query.=" FROM domicilios"; if(mysql_query ($query,$c)){ print "fichero domicilios.txt creado<br>"; }else{ print mysql_error ($c)."<br>".mysql_errno ($c); } $query="SELECT * INTO OUTFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/notas.txt'."'"; $query.=" FROM notas"; if(mysql_query ($query,$c)){ print "fichero notas.txt creado<br>"; }else{ print mysql_error ($c)."<br>".mysql_errno ($c); } $query="SELECT * INTO OUTFILE "; $query.="'".$_SERVER['DOCUMENT_ROOT'].'/php/evaluaciones.txt'."'"; $query.= " FIELDS ENCLOSED BY '\'' TERMINATED BY ',' ";
$query.=" LINES STARTING BY ' ' TERMINATED BY '\r\n' "; $query.=" FROM evaluaciones"; if(mysql_query ($query,$c)){ print "fichero evaluaciones.txt creado<br>"; }else{ print mysql_error ($c)."<r>".mysql_errno ($c); } mysql_close(); ?> Cuidado! Al exportar ficheros en entornos Windows, si se pretende que en el fichero de texto aparezca un salto de lnea no basta con utilizar la opcin por defecto de LINES TERMINATED BY '\n' sino LINES TERMINATED BY '\r\n' (salto de lnea y retorno) que son los caracteres que necesita Windows para producir ese efecto. Habr de seguirse este mismo criterio cuando se trata de importar datos desde un fichero de texto.
donde nombre_tabla es un nombre de tabla y nombre_campo es el nombre del campo de esa tabla que pretendemos visualizar para esa consulta. Esta sintaxis es idntica a la ya comentada en pginas anteriores cuando tratbamos de consultas en varias tablas. Ahora veremos las diferentes posibilidades de uso de JOIN FROM tabla1 JOIN tabla2
Suele definirse como el producto cartesiano de los elementos de la primera tabla (tabla1) por lo de la segunda (tabla2). Dicho de una forma ms vulgar, esta consulta devuelve con resultado una lista de cada uno de los registros de la primera tabla asociados sucesivamente con todos los correspondientes a la segunda. Es decir, aparecer una lnea conteniendo el primer registro de la primera tabla seguido del primero de la segunda. A continuacin, ese mismo registro de la primera tabla acompaado del segundo de la segunda tabla, y as, sucesivamente hasta acabar los registros de esa segunda tabla. En ese momento, repite el proceso con el segundo registro de la primera tabla y, nuevamente, todos los de la segunda. As, sucesivamente, hasta llegar al ltimo registro de la primera tabla asociado con el ltimo de la segunda. En total, devolver un nmero de lneas igual al resultado de multiplicar el nmero de registros de la primera tabla por los de la segunda. FROM tabla2 JOIN tabla1
Si permutamos la posicin de las tablas, tal como indicamos aqu, obtendremos el mismo resultado que en el caso anterior pero, como es lgico pensar, con una ordenacin diferente de los resultados. FROM tabla2 JOIN tabla1 ON condicion
El parmetro ON permite aadir una condicin (condicion) a la consulta de unin. Su comportamiento es idntico al de WHERE en las consultas ya estudiadas y permite el uso de las mismas procedimientos de establecimiento de condiciones que aquel operador. FROM tabla1 LEFT JOIN tabla2 ON condicion
Cuando se incluye la clusula LEFT delante de JOIN el resultado de la consulta es el siguiente: Devolvera cada uno los registros de la tabla especificada a la izquierda de LEFT JOIN sin considerar las restricciones que puedan haberse establecido en las clasulas ON para los valores de esa tabla asocindolos con aquellos de la otra tabla que cumplan las condiciones establecidas en la clasula ON. Si ningn registro de la segunda tabla cumpliera la condicin devolvera valores nulos. FROM tabla1 RIGHT JOIN tabla2 ON condicion
Se comporta de forma similar al anterior. Ahora los posibles valores nulos sern asignados a la tabla indicada a la izquierde de RIGHT JOIN y se visualizaran todos los registros de la tabla indicada a la derecha.
JOIN mltiples
Tal como puedes observar en el ejemplo, es perfectamente factible utilizar conjuntamente varios JOIN, LEFT JOIN y RIGHT JOIN. Las diferentes uniones irn ejecutndose de izquierda a derecha (segn el orden en el que estn incluidos en la sentencia) y el resultado del primero ser utilizado para la segunda unin y as sucesivamente. En cualquier caso, es posible alterar ese orden de ejecucin estableciendo otras prioridades mediante parntesis.
UNION de consultas
MySQL permite juntar en una sola salida los resultados de varias consultas. La sintaxis es la siguiente: (SELECT ...) UNION ALL (SELECT ...) UNION ALL (SELECT ...) Cada uno de los SELECT ha de ir encerrado entre parntesis.
/* devuelve cada uno de los registro de la tabla alumnos. Si existe un domicilio con igual DNI lo insertar. Si no existiera insertar valores nulos en esos campos $query[]="SELECT * FROM alumnos LEFT JOIN domicilios ON domicilios.DNI=alumnos.DNI"; /* Se comporta de forma idntica al anterior. Ahora insertar todos los registros de domicilios y los alumnos coincidentes o en su defecto campos nulos.*/ $query[]="SELECT * FROM domicilios LEFT JOIN alumnos ON domicilios.DNI=alumnos.DNI"; /* Al utilizar RIGHT ser todos los registros de la tabla de la derecha (domicilios) los que aparezcan junto con las coincidencias o junto a campos nulos. Aparecern primero los campos de alumnos y detr los de domicilios*/ $query[]="SELECT * FROM alumnos RIGHT JOIN domicilios ON (domicilios.DNI=alumnos.DNI AND alumnos.Nombre LIKE 'A%')"; /* Consulta de nombre, apellido y localidad de todos los alumnos cuyo nombre empieza por A */ $query[]="SELECT alumnos.Nombre, alumnos.Apellido1,alumnos.Apellido2, domicilios.poblacion FROM alumnos JOIN domicilios ON (domicilios.DNI=alumnos.DNI AND alumnos.Nombre LIKE 'A%')"; # una consulta resumen de nos permitir visualizar una lista con nombre # y apellidos de alumnos su direccin y localidad del domicilio # el nombre de la evaluacin y su calificacin. # Si no hay datos de poblacin insertar ---- en vez del valor nulo # y si no hay calificacin en una evaluacin aparecer N.P. # La consulta aparecer agrupada por evaluaciones /* iniciamos el select especificando los campos de las diferentes tablas que prentendemos visualizar */ $q="(SELECT alumnos.Nombre,alumnos.Apellido1,"; $q.=" alumnos.Apellido2,domicilios.calle,"; # al incluir IFNULL visualizaremos ---- en los campos cuyo resultado # sea nulo $q.=" IFNULL(domicilios.poblacion,''),"; $q.=" evaluaciones.nombre_evaluacion,"; # con este IFNULL aparecer N.P. en las evaluaciones no calificadas. $q.=" IFNULL(notas.calificacion,'N.P.')"; # especificamos el primer JOIN con el que tendremos como resultado una lista # de todos los alumnos con sus direcciones correspondientes # por efecto de la clausula ON. # Al poner LEFT se incluiran los alumnos que no tuvieran # su direccin registrada en la tabla de direccione $q.=" FROM (alumnos LEFT JOIN domicilios"; $q.=" ON alumnos.DNI=domicilios.DNI)"; # al unir por la izquierda con notas tendramos todos los resultados # del JOIN anterior asociados con con todas sus calificaciones # por efecto de la clasula ON $q.=" LEFT JOIN notas ON notas.DNI=alumnos.DNI"; # al aadir esta nueva unin por la DERECHA con la tabla evaluaciones # se asociara cada uno de los resultados de las uniones anteriores # con todos los campos de la tabla evaluaciones con lo que resultara # una lista de todos los alumnos con todas las calificaciones # incluyendo un campo en blanco (sera sustituido por N.P:) # en aquellas que no tuvieran calificacin registrada $q.=" RIGHT JOIN evaluaciones"; $q.=" ON evaluaciones.NUMERO=notas.evaluacion "; /* la clausula WHERE nos permite restringir los resultados a los valores correspondientes nicamente a la evaluacin nmero 1*/ $q.=" WHERE evaluaciones.NUMERO=1)"; # cerramos la consulta anterior con el parntesis. Observa que lo # hemos abierto delante del SELECT e insertamos UNION ALL
# para que el resultado de la consulta anterior aparezca # seguido del correspondiente a la incluida despus de UNION ALL $q.=" UNION ALL"; #iniciamos (tambin con parntesis) la segunda consulta # que ser identica a la anterior salvo el WHERE # ser modificado para extraer datos de la evaluacin n2 $q.="(SELECT alumnos.Nombre,alumnos.Apellido1,"; $q.=" alumnos.Apellido2,domicilios.calle,"; $q.=" IFNULL(domicilios.poblacion,''),"; $q.=" evaluaciones.nombre_evaluacion,"; $q.=" IFNULL(notas.calificacion,'N.P.')"; $q.=" FROM (alumnos LEFT JOIN domicilios"; $q.=" ON alumnos.DNI=domicilios.DNI)"; $q.=" LEFT JOIN notas ON notas.DNI=alumnos.DNI"; $q.=" RIGHT JOIN evaluaciones"; $q.=" ON evaluaciones.NUMERO=notas.evaluacion"; $q.=" WHERE evaluaciones.NUMERO=2)"; # hemos cerrado el parentesis de la consulta anterior # e incluimos un nuevo UNION ALL para consultar los datos # correspondientes a la tercera evaluacin $q.=" UNION ALL"; $q.="(SELECT alumnos.Nombre,alumnos.Apellido1,"; $q.=" alumnos.Apellido2,domicilios.calle,"; $q.=" IFNULL(domicilios.poblacion,''),"; $q.=" evaluaciones.nombre_evaluacion,"; $q.=" IFNULL(notas.calificacion,'N.P.')"; $q.=" FROM (alumnos LEFT JOIN domicilios"; $q.=" ON alumnos.DNI=domicilios.DNI)"; $q.=" LEFT JOIN notas ON notas.DNI=alumnos.DNI"; $q.=" RIGHT JOIN evaluaciones"; $q.=" ON evaluaciones.NUMERO=notas.evaluacion"; $q.=" WHERE evaluaciones.NUMERO=3)"; # incluimos la variable $q en el array de consultas $query[]=$q; # leemos el array y visualizamos el resultado # cada consulta a traves de la llamada a la funcion visualiza # a la que pasamos el resultado de la consulta # y la cadena que contiene las sentencias de dicha consulta foreach($query as $v){ visualiza(mysql_query($v,$c),$v); } function visualiza($resultado,$query){ PRINT "<BR><BR><i>Resultado de la sentencia:</i><br>"; print "<b><font color=#ff0000>"; print $query."</font></b><br><br>"; PRINT "<table align=center border=2>"; while ($registro = mysql_fetch_row($resultado)){ echo "<tr>"; foreach($registro as $valor){ echo "<td>",$valor,"</td>"; } } echo "</table><br>"; } ?>
Ejecutar script
La ejecucin de primero de los ejemplos manteniendo el valor por defecto nos dar la respuesta esperada que es la lista de todas las personas de la tabla cuyo nombre coincide con Telesfora. Si hacemos lo mismo con el segundo ejemplo la respuesta ser totalmente inesperada. Hemos pedido una lista de personas cuyo nombre coincida con ' or '34=34 y, contra todo pronstico (no hay nadie que se llame as en nuestra tabla) nos aparece una lista de todos los registros de la tabla. La explicacin es la siguiente. La clasula WHERE de la consulta contiene lo siguiente: WHERE (Nombre='$nombre'). Al recibir el valor' or '34=34 sustituir $nombre por ' or '34=34 y se convertir en: WHERE (Nombre='' or '34=34'). Es evidente que 34 es siempre igual a 34 como lo sera 13=13 o 1=1. Por lo tanto la condicin se cumple sea cual sea el nombre y por esa razn nos aparece la lista de todos los registros. Puede que aqu no tenga demasiada importancia pero imagina que ese formulario se usa para comprobar un nombre de usuario y una contrasea en una tabla de usuarios. Estaramos accediendo sin dificultad alguna a un lugar al que no nos estara permitido. Para evitar la posibilidad de ese efecto indeseado (inyeccin de cdigo) PHP dispone de la funcin: mysql_real_escape_string(cadena) que hace una llamada a la librera MySQL del mismo nombre y para que escape los caracteres especiales contenidos en lacadena de forma que sea mucho ms seguro su uso a travs de mysql_query(). Los caracteres que son escapados son los siguientes:\x00, \n, \r, \, ', " y \x1a. Se convertiran en: \\x00, \\n, \\r, \\\, \', \" y \\x1a con lo cual la cadena ' or '34=34 se convertira en \' or \'34=34 y la clasula anteriormente comentada se convertira en WHERE (Nombre='\' or \'34=34') con lo cual ya no se producira el efecto indeseado y se evitara el riesgo de uso inadecuado.
Cuidado! Dado que la funcin mysql_real_escape_string() se utiliza para hacer una llamada a la librera MySQL del mismo nombre, para su uso es necesario que el servidor MySQL est activo. De lo contrario se producira un error. Si se van a insertar datos binarios es necesario utilizar mysql_real_escape_string() o addslashes() con preferencia de la primera.
Aunque los desarrolladores de PHP anuncian su prxima desaparicin, en la actualidad hay en el fichero php.ini una directiva llamadamagic_quotes_gpc cuyo valor por defecto es Off. Si cambiramos esa directiva a On (o si usramos un servicio externo que la tuviera configurada de esta forma) todos los datos recibidos por medio de los mtodos GET o POST seran tratados por la funcin: addslashes(cadena)
que devuelve la cadena despus de haber escapado los carcteres ',", \ y NUL (el byte NULL). La accin de addslashes puede deshacerse utilizando la funcin stripslashes(cadena_escapada)
que quita los carcteres de escape aadidos por addslashes devolviendo la cadena original. Para comprobar como est configurada la directiva magic_quotes_gpc disponemos de la funcin:
get_magic_quotes_gpc() que devuelve un valor booleano. True si est configurada como On y False en caso de estarlo como Off.
Filtrado de cdigo
Mediante un proceso como el que puedes ver en el cdigo fuente que se incluye a continuacin puede realizarse un filtrado de los eventuales intentos de inyeccin de cdigo. Su funcionamiento es el siguiente: Leemos toda la informacin que se recibe en las variables superglobales $_GET y $_POST. Recorremos los arrays que recogen esos resultados sustituyendo sus valores por los obtenidos de la aplicacin de una funcin que realiza el filtrado. La funcin que realiza el filtrado comprueba el estado de magic_quotes. Caso de estar configuradas con On revierte los caracteres escapados para impedir que se dupliquen los carcteres de escape. Comprueba si es numrico el valor recibido y en caso de serlo lo devuelve sin ninguna modificacin. Si el valor recibido no es numrico aplica la funcin mysql_real_escape_string y devuelve el resultado dentro de unas comillas simples. De esta forma podramos despreocuparnos de poner comillas al valor de la variable en la clasula WHERE. Si se trata de un nmero no las riquere y si se trata de una cadena el valor recibido ya las incluye.
<?php if(is_array($_GET)){ foreach ($_GET as $_GET_indice=>$_GET_valor){ $_GET[$_GET_indice]=filtro_seguridad($_GET_valor); } } if(is_array($_POST) ){ foreach ($_POST as $_POST_indice=>$_POST_valor){ $_POST[$_POST_indice]= filtro_seguridad($_POST_valor); } } function filtro_seguridad($valor){ /* comprueba si estn activas las magic_quotes y, en caso de estarlo revierte su accin mediante stripslashes */ if (get_magic_quotes_gpc()) $valor = stripslashes($valor); /* por compatibilidad entre versiones Windows - Ubuntu abrimos una conexin con MySQL antes de aplicar mysql_real_escape_string */ $c=mysql_connect("localhost","pepe","pepa"); /* con la certeza de que estamos ante la cadena original aplicamos la funcin mysql_real_escape_string a todas las cadenas no numricas */ if (!is_numeric($valor)) $valor = "'" .mysql_real_escape_string($valor) . "'"; /* cerramos la conexion y devolvemos el resultado*/ mysql_close($c); return $valor; } ?>
Hemos guardado este cdigo en un fichero llamado no_inyeccion.inc.php" y hemos hecho dos modificaciones en el ejemplo anterior. Por una parte hemos incluido este fichero mediante la opcin include y por otra hemos quitado las comillas a WHERE (Nombre='$nombre')dejndolo como WHERE (Nombre=$nombre). Este es el ejemplo resultante:
Ejecutar consulta Ver cdigo fuente
El primer paso para corregir esa vulnerabilidad ser borrar los usuarios dejando slo el usuario pepe que es el que hemos creado al instalar MySQL. Para ello, con el servidor MySQL activo, abriremos http://localhost/phpMyAdmin/ editaremos la tabla user correspondiente a la base de datos mysql y borraremos los usuarios, dejando nicamente al usuario pepe.
Una vez realizados estos cambios, deberamos cerrar el servidor MySQL y reiniciarlo con la nueva configuracin. A partir de aqu, cuando tratamos de acceder de nuevo a PHPMyAdmin nos aparecer un mensaje de error tal como el que vemos en la imagen.
PHPMyAdmin nos dar este mensaje de error porque su configuracin por defecto utiliza el usuario root que ya no existe. Acabamos de borrarlo!
config.inc.php config.inc.php
Cambios Donde dice:
168
$cfg['Servers'][$i]['auth_type'] = 'config';
cambiar por:
$cfg['Servers'][$i]['auth_type'] = 'http';
Donde dice:
218
$cfg['Servers'][$i]['nopassword'] = true;
cambiar por:
$cfg['Servers'][$i]['nopassword'] = false;
Donde dice:
345
$cfg['Servers'][$i]['AllowNoPasswordRoot'] = true;
cambiar por:
$cfg['Servers'][$i]['AllowNoPasswordRoot'] =false; Al cambiar config por http estaremos establecimiento este ltimo valor como mtodo de autentificacin de los usuarios. Los otros dos cambios (que ahora hacemos igual a false) significan que no vamos a permitir el acceso sin contrasea a ningn usuario, incluido un eventual usuario root sin contrasea que pudiera quedar registrado desde el proceso inicial de instalacin.
Acceso a PHPmyAdmin
A partir del momento que hayamos hecho los cambios anteriores, cada vez que tratemos de acceder a http://localhost/phpmyadmin/ va a aparecer una ventana como la que vemos en la imagen. Ser necesario introducir un nombre de usuario vlido (pepe en nuestro caso). Nos desaparecer el mensaje de advertencia y ya podremos gestionar nuestras bases de datos de forma un poco ms segura.
Como puedes ver se utiliza una sintaxis muy prxima a la de PHP (<?php y ?>) esta vez con un xml obligatorio y situado inmediatamente detrs de <?. Cuando usamos la configuracin short_open_tag=off (descrita aqu) estaremos diferenciando claramente las etiquetas php (<?php) de las XML que comienzan por <?xml.
Respecto al atributo version se le asigna el valor 1.0 ya que esta es la nica versin existente hasta el momento. Esta primera lnea de los documentos XML, conocida como prlogo, puede incluir otros atributos que comentaremos ms adelante. Si creramos un documento con esa nica lnea, la visualizacin sera la que puedes ver pulsando aqu. Como puedes observar el mensaje de error se produce porque un documento XML ha de tener obligatoriamente un cuerpo formado por un nico elemento (elemento raz definido por una etiqueta de apertura y otra de cierre) que ser que vaya a contener a todos los dems elementos que puedan incluirse en el documento. Dicho de otra forma, los documentos XML han de incluir, a continuacin de la lnea prlogo, una etiqueta del tipo <nombre_etiqueta> y han de acabar con </nombre_etiqueta> pudiendo ser nombre_etiqueta cualquier palabra que cumpla la especificacin XML 1.0 que establece que un nombre empieza con una letra o uno o ms signos de puntuacin, y contina con letras, dgitos, guiones, rayas, dos puntos o puntos, denominados de forma global como caracteres de nombre. Los nombres que empiezan con la cadena "xml" se reservan para la estandarizacin de esta o de futuras versiones de esta especificacin. Debemos tener muy presente que los nombres de las etiquetas o marcas son sensibles a maysculas y minsculas. La estructura de un documento XML recuerda mucho los bucles anidados (siempre uno dentro del otro) y/o la interpretacin matemtica de las estructuras delimitadas por parntesis, corchetes y/o llaves. Cada elemento XML delimitado por sus etiquetas de apertura y cierre puede tener como contenido ms elementos, cadenas de caracteres, ambas cosas, o carecer de contenido (elemento vaco). Lneas de comentario las lneas de comentario tienen una sintaxis idntica a la utilizada para el mismo fin en la edicin HTML. Todo comentario comienza con <!-- y acaba con --> Etiquetas con atributos De forma similar al HTML en las marcas (de apertura) XML pueden incluirse los atributos que se desee siempre que se utilice la siguiente sintaxis: <marca atributo="valor" > <marca atributo='valor' >
siendo en este caso obligatorio que los valores vayan entre comillas (simples o dobles). Dentro de una misma etiqueta podemos incluir tantos atributos como deseemos y, de igual forma que en aquellas, tambin a los atributos podemos asignarles el nombre que deseemos. Caracteres especiales Puede ocurrir que los textos que pretendamos introducir dentro de un elemento requieran el uso de caracteres especiales que puedieran provocar conflictos con los utilizados para delimitar etiquetas y/o valores de los atributos. En XML existen entidades que pueden utilizarse para que esos caracteres sean interpretados como texto y no como elementos de marcado. Son estos: Entidad & < > ' " Caracter & < > ' "
Otra forma de incluir informacin que contenga caracteres especiales puede ser esta: <![CDATA[ caracteres raros ]]>
donde pueden incluirse cualesquiera caracteres con la excepcin de la cadena ]]> que se confundira con el cierre del bloque CDATA.
En las imgenes podemos ver los resultados de la comprobacin de un fichero. En la primera de la ventanas elegimos la opcinValidate by Direct Imput, pegamos el contenido de nuestro documento el rea del texto del formulario, pulsamos el botn check y obtenemos el resultado de la validacin y los eventuales mensajes de error o advertencia.
El origen del problema, en este caso, son los caracteres con tilde. El primer documento ha sido elaborado utilizando el Notepad++ y guardando con el formato por defecto (ANSI) de este editor. El segundo documento es el resultado de abrir el documento anterior con el bloc de notas de Windows y guardarlo sin modificar su contenido utilizando la opcin de codificacin UTF8 tal como puedes ver en la imagen.
Habramos obtenido igual resultado si al crear un archivo nuevo en Notepad++ hubiramos elegido la opcin UTF-8 tal como puedes ver en esta imagen.
Otros ejemplos
<?xml version="1.0" ?> <!-- Todo el contenido ha de ir dentro de esta etiqueta --> <ContieneTodo> <!-- La parte1 contiene informacin en forma de texto --> <parte1> Estos son los datos de la parte1 </parte1> <!-- Dentro de la parte2 incluiremos dos nuevas etiquetas con sus datos --> <parte2> Aqui pueden ir datos y tambin nuevas etiquetas <parte2_1> Incluimos ms datos, ahora en la parte 2_1 </parte2_1> Fuera de la parte 2_1 podemos aadir datos <parte2_2> Una nueva etiqueta y nuevos datos </parte2_2> </parte2> <!-- Aqui incluimos apertura y cierre en la misma etiqueta es una etiqueta vaca --> <parte3 /> </ContieneTodo>
ejemplo473.xml
Cuidado! Recuerda que los nombres de las etiquetas son sensibles a maysculas/minsculas por lo tanto < /contieneTodo>no cerrara < ContieneTodo> Tampoco debes olvidarte de guardar los documentos xml con codificacin UTF-8.
<sexo>Hembra</sexo> <comentarios>Es la < de 17 hermanos</comentarios> </alumno> </alumnos> <!-- Establecemos un elemento (profes) que va a contener los datos de los profesores (lo marcamos en magenta) --> <profes> <!-- El nmero de orden y el sexo de los profesores los insertamos ahora como atributos del elemento profe. Es una opcin alternativa a la usada en el caso de los alumnos --> <profe sexo="Varon" numero="1"> <nombre>Alejandro</nombre> <apellidos>Iglesias Fernndez</apellidos> <comentarios></comentarios> </profe> <!-- Los comentarios relativos a esta profesora los incluimos usando CDATA para evitar posibles conflictos con los caracteres especiales --> <profe sexo="Hembra" numero="2"> <nombre>Liliana</nombre> <apellidos>Fernndez de Arriba</apellidos> <comentarios> <![CDATA[ Es la < de los ^profes^ y "profas" ]]> </comentarios> </profe> </profes> <!-- incluimos un nuevo elemento padres que, por el momento, dejamos vaco --> <padres> </padres> </cuerpo_del_XML>
ejemplo474.xml
<?php /* establecemos una conexin con la base de datos ejemplos de MySQL */ $base="ejemplos"; $tabla="demo4"; $conexion=mysql_connect("localhost","pepe","pepa"); mysql_select_db($base,$conexion); /*leemos todos los campos de la tabla y todos los registros */ $resultado= mysql_query("SELECT * FROM $tabla" ,$conexion); /* inicializamos una variable con la primera etiqueta obligatoria de los ficheros xml. Ponemos \n para incluir un salto de lnea */ $xml= "<?xml version=\"1.0\" ?>\n"; /* ponemos la etiqueta de apertura del elemento raiz. En este caso le asignamos el nombre de la tabla aunque podramos ponerle cualquier otro nombre y lo agregamos alla variable que recoger toda la informacin */ $xml.= "<".$tabla.">\n"; /* leemos todas la filas del resultado filtrando aquellos elementos de array asociativo sern precisamente esos indices los que utilizaremos para asignar nombre a los elementos hijos del array */ while ($registro = mysql_fetch_array($resultado,MYSQL_ASSOC)){
/* cada registro ser un elemento xml. Le pondremos como nombre usuario aunque podramos ponerles cualquier otro nombre y lo agregamos a la variable que recoger todo*/ $xml.= "<usuario>\n"; /* leemos el buche de los resultado y vamos aadiendo etiquetas de apertura con el mismo nombre que el ndice asociativo, con el valor contenido en el array (codificado utf8 para evitar problemas de lectura del xml y despus ponemos la etiqueta de cierre con el mismo nombre que la de apertura) */ foreach($registro as $indice=>$valor){ $xml.= "<".$indice.">".utf8_encode($valor)."</".$indice.">\n"; } /* leido el registro completo aadimos la etiqueta de cierre del usuario */ $xml.= "</usuario>\n"; } /* aadimos la etiqueta de cierre del elemento raiz */ $xml.= "</".$tabla.">\n"; /* cerramos la conexin con la base de datos */ mysql_close(); /* escribimos el contenido de la variable que recoge toda la informacin en un fichero xml y colocamos un enlace para poder visualizarlo en el navegador */ if (file_put_contents("demo4.xml",$xml)){ print '<a href="demo4.xml">Ver el fichero demo4.xml que acaba de crearse</a>'; }else{ print "El fichero demo4.xml no ha podido crearse. Ha habido un error"; } ?>
Crear fichero XML
Este otro ejemplo es una modificacin del anterior. En este caso hemos optado por convertir uno de los campos de la tabla en atributo de uno de los elementos del fichero XML.
<?php /* establecemos una conexin con la base de datos ejemplos de MySQL */ $base="ejemplos"; $tabla="demo4"; $conexion=mysql_connect("localhost","pepe","pepa"); mysql_select_db($base,$conexion); /*leemos todos los campos de la tabla y todos los registros */ $resultado= mysql_query("SELECT * FROM $tabla" ,$conexion); /* inicializamos una variable con la primera etiqueta obligatoria de los ficheros xml. Ponemos \n para incluir un salto de lnea */ $xml= "<?xml version=\"1.0\" ?>\n"; /* ponemos la etiqueta de apertura del elemento raiz. En este caso le asignamos el nombre de la tabla aunque podramos ponerle cualquier otro nombre y lo agregamos alla variable que recoger toda la informacin */ $xml.= "<".$tabla.">\n"; /* leemos todas la filas del resultado filtrando aquellos elementos de array asociativo sern precisamente esos indices los que utilizaremos para asignar nombre a los elementos hijos del array */ while ($registro = mysql_fetch_array($resultado,MYSQL_ASSOC)){ /* cada registro ser un elemento xml. Le pondremos como nombre usuario e incluiremos ahora el Sexo como atributo en la etiqueta usuario asignando como valor el contenido de el elemento del mismo nombre del array resultante de la lectura de la tabla*/ $xml.= "<usuario Sexo='".$registro['Sexo']. "' >\n";
/* leemos el buche de los resultado y vamos aadiendo etiquetas de apertura con el mismo nombre que el ndice asociativo, con el valor contenido en el array (codificado utf8 para evitar problemas de lectura del xml y despus ponemos la etiqueta de cierre con el mismo nombre que la de apertura Excluimos el de indice Sexo que ya ha sido incluido como atributo del usuario */ foreach($registro as $indice=>$valor){ if ($indice !='Sexo'){ $xml.= "<".$indice.">".utf8_encode($valor)."</".$indice.">\n"; } } /* leido el registro completo aadimos la etiqueta de cierre del usuario */ $xml.= "</usuario>\n"; } /* aadimos la etiqueta de cierre del elemento raiz */ $xml.= "</".$tabla.">\n"; /* cerramos la conexin con la base de datos */ mysql_close(); /* escribimos el contenido de la variable que recoge toda la informacin en un fichero xml y colocamos un enlace para poder visualizarlo en el navegador */ if (file_put_contents("demo4_1.xml",$xml)){ print '<a href="demo4_1.xml">Ver el fichero demo4_1.xml que acaba de crearse</a>'; }else{ print "El fichero demo4_1.xml no ha podido crearse. Ha habido un error"; } ?>
Crear fichero XML
El DOM (Document Object Model) presenta un documento XML como una estructura de rbol.
Tipos de nodos
Cada uno de los elementos (nodos) que puede contener un documento corresponde a uno de los tipos siguientes:
1 2 3 4 5 6
ELEMENT NODE ATTRIBUTE NODE TEXT NODE CDATA SECTION NODE ENTITY REFERENCE NODE ENTITY NODE PROCESSING INSTRUCTION 7 NODE 8 COMMENT NODE 9 DOCUMENT NODE 10 DOCUMENT TYPE NODE DOCUMENT FRAGMENT 11 NODE 12 NOTATION NODE
siendo los verdaderamente tiles para nuestros fines los sealados en rojo en la tabla anterior. Se refieren a los componentes de los documentos XML descritos en la pgina anterior.
La clase DOMDocument
El constructor de la clase DOMDocument crear un objeto utilizando la sintaxis siguiente: $objeto= new DOMDocument('version','codificacion') donde $objeto es el identificador del nuevo objeto y donde version y codificacion son dos cadenas opcionales que incluiran respectivamente el nmero de la versin del nuevo documento XML (actualmente solo es posible la versin 1.0) y el formato de codificacin del documento con valores tales como 'utf-8' o ''.
Propiedades de DOMDocument
Los objetos creados por la clase DOMDocument poseen, entre otras, las siguientes propiedades: encoding Recoge en una cadena el tipo de codificacin del documento tal como se especifica en el prlogo del mismo. Si no hubiera sido establecida el valor de esta propiedad sera una cadena vaca. xmlVersion Recoge en una cadena la versin del documento tal como se especifica en el prlogo del mismo. Como ocurra en el caso anterior, si no hubiera sido establecida su valor sera una cadena vaca. formatOutput Da formato a la salida aplicando sangras y espacios extra. Permite valores booleanos (true false). Por defecto toma el valor false. preserveWhiteSpace Es un valor booleano (TRUE por defecto) que indica si deben mantenerse los espacios redundandes en los contenidos del documento. nodeType Esta propiedad no es modificable. Devuelve un nmero comprendido entre 1 y 12 (son los de la tabla de tipos de nodos incluida ms arriba) que se corresponde con el tipo de nodo al que pertenece el objeto actual. nodeName Esta propiedad, que tampoco es modificable, contiene el nombre del nodo actual. nodeValue En esta propiedad se recoge el valor del contenido del nodo actual. Es modificable de la siguiente forma: $objeto->nodeValue=nuevo_valor
Mtodos de DOMDocument
Algunas de las funciones (mtodos) de esta clase son las siguientes: $objeto->load('fichero'); este mtodo permite incluir en un objeto DOMDocument el contenido de un fichero cuyo nombre y path se especifican en el parmetrofichero.
$raiz=$objeto->documentElement este mtodo permite recoger en un objeto llamado $raiz el contenido del nodo raz del objeto XML. $hijos=$objeto->childNodes este mtodo permite recoger en un objeto llamado $hijos el conjunto de los nodos hijos del $objeto $un_hijo=$objeto->childNodes->item(indice) este mtodo permite recoger en un objeto llamado $un_hijo el nodo hijo del $objeto cuya posicion es sealada por el nmero indice. $otro_objeto=$objeto->getElementsByTagName('nombre') este mtodo crea un objeto $otro_objeto que contiene todos los nodos del objeto $objeto cuyo nombre coincide con nombre. $otro_elemento=$objeto->getElementsByTagName('nombre')->item(indice) es una ampliacin de caso anterior. Ahora $otro_elemento contiene nicamente el nodo que ocupa la posicin sealada por indice en el conjunto de nodos cuyo nombre coincide con nombre. $otro_elemento=$objeto->getElementsByTagName('nombre')->item(indice)->getElementsByTagName('otro_nombre')>item(otro_indice) Una nueva ampliacin de casos anteriores. Ahora $otro_elemento contiene nicamente el nodo que ocupa la posicin sealada porotro_indice en el conjunto de nodos cuyo nombre coincide con otro_nombre y que a la vez son hijos del elemento de ndice indice del conjunto formado por los nodos de nombre nombre contenidos en el $objeto. La cadena podra alargarse con nuevas inclusiones. En este ejemplo puedes ver la forma de acceder a los diferentes nodos de un documento XML.
<?php /* creamos un objeto DOM con nombre $mi_XML*/ $mi_XML = new DOMDocument(); /* incluimos el fichero ejemplo474.xml en ese objeto */ $mi_XML->load('ejemplo474.xml'); /* leamos algunas de las propiedades de este objeto */ print "La propiedad encoding vale: ".$mi_XML->encoding."<br>"; print "La propiedad xmlVersion vale: ".$mi_XML->xmlVersion."<br>"; print "La propiedad formatOutput vale: ".$mi_XML->formatOutput."<br>"; print "preserveWhiteSpace vale: ".$mi_XML->preserveWhiteSpace ."<br>"; print "Como llegar al valor Juan <br><b>"; print $mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)-> childNodes->item(1)->nodeValue; /* para mayor comodidad podramos haber creado un objeto de esta forma: */ $juanito=$mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)>childNodes->item(1); /* al imprimir el valor de la propiedad nodeValue del nuevo objeto dar el mismo resultado que en el caso anterior */ print "</b><br />tambin as se llega: ".$juanito->nodeValue; print "</b><br />Otra forma de llegar: "; print $mi_XML->documentElement->getElementsByTagName('alumno')->item(0)-> getElementsByTagName('nombre')->item(0)->nodeValue; /*$mi_XML->documentElement nos llevara al nodo raz. getElementByTagName('alumno') nos dara los nodos (contenidos en el raiz) que tienen por nombre alumno. El item(0) que le sigue indicara que vamos al primero de los nodos alumno y all mediante getElementsByTagName('nombre')
buscaramos el array que contiene los elementos nombre de ese alumno concreto. Como solo hay un nombre estar identificado por el ndice 0 (item(0)) y de este ya extraeramos el valor */ print "</b><br>Vamos a conocer el nombre del nodo padre de Juan:<br><b>"; print $juanito->parentNode->nodeName; print "</b><br>Vamos a conocer el nombre del nodo abuelo de Juan:<br><b>"; print $juanito->parentNode->parentNode->nodeName; print "</b><br />El bisabuelo de Juan se llama:<br><b>"; print $mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(3)>childNodes->item(1)-> parentNode->parentNode->parentNode->nodeName; print "</b><br />Tendr Juan tatarabuelo ?<br><b>"; print $juanito->parentNode->parentNode->parentNode->parentNode->nodeName."</b>"; /* creemos un nuevo objeto con nombre $hijuela */ $hijuela=$mi_XML->childNodes->item(1)->childNodes->item(3)->childNodes->item(7)>childNodes->item(7); /* visualizemos las propiedades del nuevo objeto */ print "<br><i>El nodo se llama </i> ".$hijuela->nodeName; print " <i>es del tipo:</i> ".$hijuela->nodeType; print " y <i>contiene esto</i>: ".$hijuela->nodeValue; ?>
Ejecutar el script
Cuidado! Los mtodos crean el elemento, el comentario o el CDATA pero no lo incluye en el documento XML. Para esto es necesario recurrir a los mtodos que se incluyen a continuacin.
$objeto->(.. nodos)->appendChild($elemento); $objeto->(.. nodos)->appendChild($comentario); $objeto->(.. nodos)->appendChild($cdata); Incluyen en el nivel indicado por $objeto->(.. nodos) un nuevo elemento, comentario o CDATA que han de ser creados mediante los mtodos Create... descritos anteriormente. $objeto->insertBefore($nuevo_elemento, $otro_elemento); Incluye un elemento $nuevo_elemento precediendo a $otro_elemento incluido como segundo parmetro.
$objeto->insertBefore($nuevo_elemento, $otro_elemento->nextSibling); Incluye $nuevo_elemento en el mismo nivel y a continuacin del del $otro_elemento que precede los caracteres obligatorios ->nextSibling. $objeto->(.. nodos)->AddAttribute(atributo, valor); Aade un nuevo atributo al elemento $objeto->(.. nodos) y le asigna el valor indicado por valor. $objeto->(.. nodos)->->setAttribute(atributo, valor); Modifica el valor del atributo correspondiente al elemento $objeto->(.. nodos). $lectura= $objeto->(.. nodos)->->getAttribute(atributo, valor); Recoge en la variable $lectura el valor del atributo correspondiente al elemento $objeto->(.. nodos). $objeto->saveXML(); Recoge en una cadena el rbol de contenidos XML del objeto $objeto. Resulta muy til para visualizar los contenidos y formatos de los documentos XML con los que estamos trabajando. $objeto->save('fichero'); Permite guardar en un fichero cuyo path, nombre y extensin se indica en el parmetro fichero el contenido del objeto $objeto. En este ejemplo incluimos las diferentes opciones de uso de estos mtodos para crear un documento XML.
<?php header("content-type: text/xml"); /* Empezamos incluyendo una cabecera que especifica el tipo de documento resultante de la ejecucin de este script. Ser text/xml. De esta forma los navegadores, IE, Firefox y Opera nos permitirn ver la estructura del documento. Creamos un nuevo objeto DOMDocument en cuyo prlogo incluiremos la versin de XML (1.0) y la forma de codificacin (utf8) dentificaremos el objeto mediante el nombre \$mi_XML */ $mi_XML = new DOMDocument('1.0','utf-8'); /* Las propiedades $mi_XML->encoding habr tomado el valor utf-8. y $mi_XML->xmlVersion tendr como valor 1.0 $mi_XML->formatOutput toma por defecto el valor false, podemos modificar esa propiedad (a true) con: */ $mi_XML->formatOutput=true; /* La propiedad $mi_XML->preserveWhiteSpace toma true por defecto. Podriamos cambiarla a false de la forma siguiente: */ $mi_XML->preserveWhiteSpace=false; /* Creado el prembulo del objeto $mi_XML el paso siguiente sera crear los diferentes elementos que lo componen. El elemento raiz de nuestro esquema se llama es profesores. Lo creamos de la siguiente forma: */ $raiz=$mi_XML->CreateElement('profesores'); /* Debemos aadirlo como un hijo (Child) del objeto principal */ $mi_XML->appendChild($raiz); /* vamos a agregar algunod de comentarios. Empezamos por crearlos */ $c1=$mi_XML->CreateComment('Voy fuera de profesores');
$c2=$mi_XML->CreateComment('Voy dentro de profesores'); $c3=$mi_XML->CreateComment('Quiero ser el primero'); $c4=$mi_XML->CreateComment('Quiero ponerme antes de los profes'); $c5=$mi_XML->CreateComment('Me insertarn de otra forma'); /* los insertamos (lo importante es donde) El primer comentario ser un hijo del objeto principal y se insertar detrs del ltimo de los ya insertados (detrs del elemento profesores en este caso*/ $mi_XML->appendChild($c1); /* este comentario ira dentro del elementos profesores ya que $raiz es la variable sobre la que fue creado el elemento profesores */ $raiz->appendChild($c2); /* colocaremos a hora $c3 en primera posicion mediante insertBefore */ $mi_XML->insertBefore($c3,$raiz); /* el comentario $c4 lo vamos a colocar justamente detras de $c3 $c3 "ser el siguiente hermano de $c3" */ $mi_XML->insertBefore($c4,$c3->nextSibling); $mi_XML->getElementsByTagName('profesores')->item(0)->appendChild($c5); /* crearemos un nuevo elemento (profe) */ $un_profe=$mi_XML->CreateElement('profe'); /* lo insertamos dentro de del nodo $raiz (profesores) */ $raiz->appendChild($un_profe); /* iremos aadiendo a este profe recien creado los diferentes elementos segun el diseo del grfico del organigrama */ $un_profe->setAttribute('situacion',utf8_encode("Func en practicas")); $p1=$mi_XML->CreateElement('nombre','Antonio'); $p2=$mi_XML->CreateElement('apellidos','Lpez del Ro'); $un_profe->appendChild($p1); $mi_XML->getElementsByTagName('profe')->item(0)->appendChild($p2); $mi_XML->getElementsByTagName('profe')->item(0)->setAttribute('sexo',"varon"); $p3=$mi_XML->CreateElement('nacimiento','21-01-1978'); $p3->setAttribute('zodiaco','Acuario'); $un_profe->appendChild($p3); /* ahora va la retribucin */ $p4=$mi_XML->CreateElement('retribucion'); $p4->setAttribute('IRPF','15 %'); $p4->setAttribute('sexenios','5'); $p5=$mi_XML->CreateElement('base'); $p6=$mi_XML->CreateElement('complemento'); $p5t=$mi_XML->createTextNode('1678,32 '); $p6t=$mi_XML->createTextNode('1678,32 '); $un_profe->appendChild($p4); $p4->appendChild($p5); $p4->appendChild($p6); $p5->appendChild($p5t); $p6->appendChild($p6t); $p7=$mi_XML->CreateElement('valoracion'); $cdata =$mi_XML->createCDATASection("Inspeccin da 23/08/1998\n Llega tarde y sin corbata"); $p7->appendChild($cdata); $un_profe->appendChild($p7); /* agregado masivo de datos a partir de arrays que pueden proceder de la lectura de una base de datos */ $nombres=array('Juan','Perico','Andres','Dolores','Rosario','Alejandra'); $apellidos=array('Fernndez Gonzlez','Ruz del Olmo','Garca Garca','Daz Alonso', 'Carbajal Berrocal','Altamira del Busto'); $sexos=array('Varon','Varon','Varon','Hembra','Hembra','Hembra'); $situaciones=array ('Catedrtico','Profesor','Interino','Interina','Catedrtica','Profesora'); $nacimiento=array('14-12-1967','21-02-1981','23-04-1978','16-06-1967','05-08-1981','0310-1987'); $signo=array('Aries','Acuario','Libra','Tauro','Sagitario','Cancer');
$sueldo_base=array('1.247,32 ','1.257,22 ','1.217,02 ','1.307,20 ','2.047,95 ','1.300,00 '); $complementos=array('1.300 ','1.124 ','1.800 ','1.417 ','1.632 ','1.497 '); $irpf=array('13%','12%','23%','21%','18.5%','11%'); $sexenios=array(1,2,3,4,5,6); $valoracion=array('Excelente profesional','Manifiestamente mejorable','Necesita reciclaje', 'Impecable','Excepcional','Promete grandes xitos'); $cuenta=$mi_XML->getElementsByTagName('profe')->length; for ($i=0;$i<sizeof($nombres);$i++){ $un_profe=$mi_XML->CreateElement('profe'); $raiz->appendChild($un_profe); $un_profe->setAttribute('situacion',$situaciones[$i]); $p1=$mi_XML->CreateElement('nombre',$nombres[$i]); $p2=$mi_XML->CreateElement('apellidos',$apellidos[$i]); $un_profe->appendChild($p1); $mi_XML->getElementsByTagName('profe')->item($i+$cuenta)->appendChild($p2); $mi_XML->getElementsByTagName('profe')->item($i+$cuenta)>setAttribute('sexo',$sexos[$i]); $p3=$mi_XML->CreateElement('nacimiento',$nacimiento[$i]); $p3->setAttribute('zodiaco',$signo[$i]); $un_profe->appendChild($p3); $p4=$mi_XML->CreateElement('retribucion'); $p4->setAttribute('IRPF',$irpf[$i]); $p4->setAttribute('sexenios',$sexenios[$i]); $p5=$mi_XML->CreateElement('base'); $p6=$mi_XML->CreateElement('complemento'); $p5t=$mi_XML->createTextNode($sueldo_base[$i]); $p6t=$mi_XML->createTextNode($complementos[$i]); $un_profe->appendChild($p4); $p4->appendChild($p5); $p4->appendChild($p6); $p5->appendChild($p5t); $p6->appendChild($p6t); $p7=$mi_XML->CreateElement('valoracion'); $cdata =$mi_XML->createCDATASection($valoracion[$i]); $p7->appendChild($cdata); $un_profe->appendChild($p7); } echo $mi_XML->saveXML(); $mi_XML->save('ejemplo478.xml'); ?>
Ejecutar el script Ver documento XML
Como muestra de cual es el procedimiento para interpretar y reconocer los valores de los nodos de un documento hemos incluido este ejemplo.
Ejemplo481.php Ver cdigo fuente
<?php /* creamos un nuevo objeto y cargamo el fichero XML creado en el ejemplo anterior */ $mi_XML = new DOMDocument(); $mi_XML->load('ejemplo478.xml'); /* determinamos el numero de nodos con nombre "profe" */ $numero_profes=$mi_XML->getElementsByTagName('profe')->length; /* creamos nuevos objetos que contenga los nodos con los diferentes nombres Esta manera de hacerlo puede plantear un problema. De haber otros nodos, por ejemplo alumnos que contuvieran nombres o apellidos los recogeria todos sin discriminar a que nodo padre pertenecen */ $los_profes=$mi_XML->getElementsByTagName('profe'); $los_nombres=$mi_XML->getElementsByTagName('nombre'); $los_apellidos=$mi_XML->getElementsByTagName('apellidos'); $el_nacimiento=$mi_XML->getElementsByTagName('nacimiento'); $la_retribucion=$mi_XML->getElementsByTagName('retribucion'); $la_base=$mi_XML->getElementsByTagName('base'); $el_complemento=$mi_XML->getElementsByTagName('complemento'); $la_valoracion=$mi_XML->getElementsByTagName('valoracion'); /* recorremos el bucle de los diferentes objetos extrayendo sus valores mediante nodeValue en el caso de nodos y por medio de getAttribute en el caso de los atributos. Vamos recogiendo los diferentes valores en arrays escalares */ for ($i=0;$i<$numero_profes;$i++){ $sexo[]=$los_profes->item($i)->getAttribute('sexo'); $situacion[]=$los_profes->item($i)->getAttribute('situacion'); $nombre[]=$los_nombres->item($i)->nodeValue; $apellidos[]=$los_apellidos->item($i)->nodeValue; $nacimiento[]=$el_nacimiento->item($i)->nodeValue; $zodiaco[]=$el_nacimiento->item($i)->getAttribute('zodiaco'); $base[]=$la_base->item($i)->nodeValue; $irpf[]=$la_retribucion->item($i)->getAttribute('IRPF'); $sexenios[]=$la_retribucion->item($i)->getAttribute('sexenios'); $complemento[]=$el_complemento->item($i)->nodeValue; $valoracion[]=$la_valoracion->item($i)->nodeValue; } /* insertamos el encabezado de una tabla para presentar los resultados que tambin podran ser utilizados para crear una tabla en MySQL o para cualquier otro proposito en el que se manejen variables PHP */ ?> <table> <tr style="font-size:10px"><td>Nombre</td><td>Apellidos</td> <td>Sexo</td><td>Situacin</td><td>Fecha nacimiento</td> <td>Zodiaco</td><td>Sueldo base</td><td>Complementos</td> <td>IRPF</td><td>Sexenios</td><td>Valoracin</td></tr> <?php /*mediante este bucle creamos las sucesivas filas de la tabla */ for ($i=0;$i<sizeof($nombre);$i++){ print "<tr style='font-size:10px'><td>".$nombre[$i]."</td>"; print "<td>".utf8_decode($apellidos[$i])."</td><td>".$sexo[$i]."</td>"; print "<td>".utf8_decode($situacion[$i])."</td><td>".$nacimiento[$i]."</td>"; print "<td>".$zodiaco[$i]."</td><td>".utf8_decode($base[$i])."</td>"; print "<td>".utf8_decode($complemento[$i])."</td><td>".$irpf[$i]."</td>"; print "<td>".$sexenios[$i]."</td><td>".utf8_decode($valoracion[$i])."</td></tr>"; } print "</table><br /><br /><br />"; /* como opcin alternativa para extraer los mismos valores asegurndose que no se incluyen ms que los correspondientes a los profesores podemos extraerlos del nodo profes. Extraemos los atributos de cada uno de los objetos profe (sexo y situacin) y los dems valores los extraemos siempre del item(0) ya que el objeto nombre es hijo (nico) de profes */
$prof=$mi_XML->getElementsByTagName('profe'); for ($i=0;$i<$numero_profes;$i++){ $n_sexo[]=$prof->item($i)->getAttribute('sexo'); $n_situacion[]=$prof->item($i)->getAttribute('situacion'); $n_nombre[]=$prof->item($i)->getElementsByTagName('nombre')->item(0)->nodeValue; $n_apellidos[]=$prof->item($i)->getElementsByTagName('apellidos')->item(0)->nodeValue; $n_nacimiento[]=$prof->item($i)->getElementsByTagName('nacimiento')->item(0)>nodeValue; $n_zodiaco[]=$prof->item($i)->getElementsByTagName('nacimiento')->item(0)>getAttribute('zodiaco'); $n_base[]=$prof->item($i)->getElementsByTagName('base')->item(0)->nodeValue; $n_irpf[]=$prof->item($i)->getElementsByTagName('retribucion')->item(0)>getAttribute('IRPF'); $n_sexe[]=$prof->item($i)->getElementsByTagName('retribucion')->item(0)>getAttribute('sexenios'); $n_complemento[]=$prof->item($i)->getElementsByTagName('complemento')->item(0)>nodeValue; $n_valoracion[]=$prof->item($i)->getElementsByTagName('valoracion')->item(0)>nodeValue; } /* repetimos el proceso anterior con un pequeo cambio. Durante la codificacin/decodificacin del smbolo del euro hemos perdido ese carcter que ahora aparece sustituido por un signo de interrogacin. str_replace nos permite corregir esa deficiencia visual tal como puedes ver si comparas las dos tablas resultantes de la ejecucin de este script */ ?> <table> <tr style="font-size:10px"><td>Nombre</td><td>Apellidos</td> <td>Sexo</td><td>Situacin</td><td>Fecha nacimiento</td> <td>Zodiaco</td><td>Sueldo base</td><td>Complementos</td> <td>IRPF</td><td>Sexenios</td><td>Valoracin</td> <?php for ($i=0;$i<sizeof($nombre);$i++){ print "<tr style='font-size:10px'><td>".$n_nombre[$i]."</td>"; print "<td>".utf8_decode($n_apellidos[$i])."</td><td>".$n_sexo[$i]."</td>"; print "<td>".utf8_decode($n_situacion[$i])."</td><td>".$n_nacimiento[$i]."</td>"; print "<td>".$n_zodiaco[$i]."</td><td>".str_replace('?', '', utf8_decode($n_base[$i]))."</td>"; print "<td>".str_replace('?', '', utf8_decode($n_complemento[$i]))."</td><td>".$n_irpf[$i]."</td>"; print "<td>".$n_sexe[$i]."</td><td>".utf8_decode($n_valoracion[$i])."</td></tr>"; } print "</table><br /><br /><br />"; ?>
Ejecutar el script
<?php header ("content-type: text/plain"); /* creamos dos objetos uno llamado importador que ser el que recoja los datos de un documento preexistente y mi_XML que ser el objeto que contendr el nuevo fichero */ $importador = new DOMDocument(); $mi_XML = new DOMDocument('1.0','utf-8'); /* cargamos el documento ejemplo478.xml completo */ $importador->load('ejemplo478.xml'); /* extraemos el objeto raiz llamado profesores y objeto nico, por eso el item(0))(olvidando lneas de comentario del orginal) y lo ponemos en un objeto nuevo llamado colocar */ $colocar = $importador->getElementsByTagName("profesores")->item(0); /* el objeto mi_XML aun no contiene nada asi que crearemos un nuevo objeto y se lo agregaremos. Al ser el primer elemento ser el elemento raiz del nuevo documento*/ $nueva_raiz=$mi_XML->CreateElement('plantilla_completa'); $mi_XML->appendChild($nueva_raiz); /* insertamos los elementos extraidos del fichero importado que habamos recogido en una variable llamada colocar */ $agregar = $mi_XML->importNode($colocar, true); /* colocamos el nuevo objeto agregar como hijo de la raiz de documento */ $nueva_raiz->appendChild($agregar); /*aadimos un nuevo atributo al elemento profesores (unico, era el raiz del fichero que acabamos de importar) */ $mi_XML->getElementsByTagName("profesores")->item(0)>setAttribute('nivel','Secundaria'); /*creamos un objeto con con datos del profesores del nodo importador repitiendo lo que hemos hecho conaterioridad */ $extraer = $importador->getElementsByTagName("profesores")->item(0); /* importamos el nodo completo */ $agregar = $mi_XML->importNode($extraer, true); /* insertamos nuevamente el nodo profesores recogido previamente en el objeto agregar */ $nueva_raiz->appendChild($agregar); /* asignamos al nodo profesores recien creado item(1) el atributo nivel */ $mi_XML->getElementsByTagName("profesores")->item(1)->setAttribute('nivel','Primaria'); /* creamos un objeto primarios que contiene todos los elementos profe de estos ultimos profesores */ $primarios=$mi_XML->getElementsByTagName("profesores")->item(1)>getElementsByTagName("profe"); /* modificamos el atributo situacin de los profes de primarios */ for($i=0;$i<$primarios->length;++$i){ $cambiar=$primarios->item($i)->getAttribute('situacion'); switch ($cambiar){ case "Catedrtica": $primarios->item($i)->setAttribute('situacion','Profesora de Segundo Ciclo'); break; case "Profesor": $primarios->item($i)->setAttribute('situacion','Profesor de Primer Ciclo'); break; case "Profesora": $primarios->item($i)->setAttribute('situacion','Profesora de Primer Ciclo'); break; case "Catedrtico": $primarios->item($i)->setAttribute('situacion','Profesor de Segundo Ciclo'); break; } } /* vamos a modificar datos de nombres y apellidos para evitar los duplicado consecuencia de haber importado dos veces el mismo nodo */
$nuevos_apellidos=array('Alonso Galguera','Ruz de Alda','Alonso Aller', 'Menndez Lpez','Garca Ura','Alvarez del Campo','Feito Parrondo'); $nuevo_nombre=array ('Luis','Eduardo','Fernando','Gonzalo','Carmela', 'Luisa','Servanda'); /* recorremos los elementos primarios cambiando el valor de los nodos nombre (con item0 por tener solo un elemento) por el nuevo nombre y los apellidos por lo nuevos apellidos y adems hacemos una sustitucin de la valoracin en el caso de producirse una coincidencia */ for($i=0;$i<$primarios->length;++$i){ $primarios->item($i)->getElementsByTagName("nombre")->item(0)>nodeValue=$nuevo_nombre[$i]; $primarios->item($i)->getElementsByTagName("apellidos")->item(0)-> nodeValue=utf8_encode($nuevos_apellidos[$i]); if($primarios->item($i)->getElementsByTagName("valoracion")->item(0)-> nodeValue=="Necesita reciclaje"){ $primarios->item($i)->getElementsByTagName("valoracion")->item(0) ->firstChild->nodeValue=utf8_encode("Adems de reciclaje\n necesita un milagro"); } /* quitamos el atributo zodiaco a todos profes de primara */ $primarios->item($i)->getElementsByTagName("nacimiento")->item(0)>removeAttribute('zodiaco'); /* quitamos el atributo sexenios a todos aquellos cuya situacin empiece por Inter */ if(substr($primarios->item($i)->getAttribute("situacion"),0,5)=="Inter"){ $primarios->item($i)->getElementsByTagName("retribucion")->item(0)>removeAttribute('sexenios'); } } /*Busco a Servanda le cambio el nombre por Severina*/ for($i=0;$i<$primarios->length;++$i){ $nombre=$primarios->item($i)->getElementsByTagName("nombre")->item(0)->nodeValue; if ($nombre=="Servanda"){ $primarios->item($i)->getElementsByTagName("nombre")->item(0)>nodeValue="Severina"; } } /* visualizamos los resultados */ echo $mi_XML->saveXML(); ?>
Ejecutar el script
De esta forma, adems de familiarizarnos con el manejo de las bases de datos SQLite, conoceremos una forma alternativa de gestionar MySQL. Es por ello que a lo largo de esta pgina y las siguientes nos referirmos con frecuencia a ejemplos, situaciones y operaciones ya estudiadas en MySQL. Ahora trataremos de hacer algo muy similar a aquello pero utilizando de forma exclusiva la extensinPDO.
Configuracin de PHP
El uso de PDO requiere el uso de una extensin especfica de PHP para cada uno de los tipos de bases de datos que pretendamos gestionar. En nuestro caso vamos a manejar MySQL y SQLite lo que requiere que, bajo Windows, usemos las extensionesextension=php_pdo_sqlite.dll y extension=php_pdo_mysql.dll Habremos de editar el fichero php.ini, buscar esas dos extensiones, descomentarlarlas (quitar el punto y coma que llevan delante), guardar los cambios y reiniciar el servidor. Cuando se trata de Ubuntu es preciso realizar la siguiente instalacin:
sudo apt-get install php5-sqlite con lo cual, en cualquiera de los dos casos, una vez reiniciado el servidor la pgina http://localhost/info.php debera mostrarnos una informacin similar a esta:
Aunque iremos viendo los diferentes mtodos de esta clase tiene particular inters que empecemos conociendo un los ms importantes: $objeto->query(SENTENCIA) que permite ejecutar cualquier SENTENCIA SQL sobre el $objeto sea cual fuere el tipo de base de datos en uso. Quiere ello decir que usaremos este mismo mtodo para cualquier proceso de: creacin, modificacin, baja, o consulta de bases datos y tablas.
<?php /* creamos un objeto PDO con el nombre $dbSQLite. Es importante que el parmetro que se incluye comience por sqlite: (esa palabra es la indica el driver debe utilizar PHP para gestionar la base de datos es SQLite)y a continuacin la cadena con la ruta y nombre del fichero que contendr la base de datos */ $dbSQLite= new PDO('sqlite:./images/baseSQLite.zpq'); /* una opcin un poco ms sofisticada podra utilizar una funcin y devolvernos un mensaje de confirmacin o de error. */ function conecta($nombre){ if ($db = new PDO('sqlite:'.$nombre)){ print "Creado o abierto el fichero SqLite: ".$nombre.'<br />'; return($db); } else { print "Error: No puede conectarse con la base de datos.<br />"; print "<br />".$db->errorInfo()."<br />"; exit(); } } /* si hacemos una llamada a esta funcin pasndole como parmetro el nombre de la base de datos y (opcionalmente) la ruta habremos creado un nuevo objeto y un nuevo fichero de base de datos */ $dbSQLite1= conecta('practicar'); /* destruimos el objeto con ello desconectamos de la base de datos */ $dbSQLite1=NULL; $dbSQLite=NULL; /* destruimos los objetos (la conexin) pero los ficheros se mantienen*/ ?>
ejemplo482.php
Cuidado! Es importante elegir un lugar adecuado para almacenar las bases de datos SQLite. Al tratarse de un nico fichero si lo dejamos dentro del directorio raz (htdocs en la configuracin aqu descrita) o en uno de sus directorios es obvia su vulnerabilidad. Fjate que este enlace http://www.rinconastur.net/php/ejemploSQLite permite descargar sin problema
alguno la base de datos SQLite que hemos incluido como ejemplos. Adems, al carecer de contrasea, los datos que contiene son totalmente accesibles. La forma de evitar o al menos paliar ese riesgo sera almacenar este fichero fuera del document_root (htdocs) de la misma forma que hacamos con las contraseas de acceso a MySQL
<?php function conecta($base){ $db = new PDO('mysql:host=localhost','pepe','pepa'); /* crea la base de datos si no existe */ $db->query("CREATE DATABASE IF NOT EXISTS ".$base); /* crea un nuevo objeto usando la base de datos pasada como parmetro sin riesgo de error por inexistencia de la base */ if($db1 = new PDO('mysql:host=localhost;dbname='.$base,'pepe','pepa')){ print "Creado o abierta la base de datos MySQL: ".$base.'<br />'; return($db1); } else { print "Error: No puede conectarse con la base de datos.<br />"; print "<br />".$db1->errorInfo()."<br />"; exit(); } } /* Hacemos una llamada a esta funcin pasndole como parmetro el nombre de la base de datos */ $dbSQLite1= conecta('practicar'); ?>
ejemplo483.php
Cuidado! Presta atencin a la sintaxis sin olvidar la correcta ubicacin de las comillas. $objeto=new PDO ("mysql:host=localhost","pepe","pepa") o $objeto=new PDO ("mysql:host=localhost; dbname=ejemploSQLite", "pepe", "pepa") sera la sintaxis vlida. Utiliza siempre comillas dobles (estas " ") en este tipo de sentencias. Si los nombres de bases de datos, usuarios, host y/o contraseas proceden de variables la sintaxis que debers utilizar ser esta: new PDO("mysql:host=$host;dbname=$base_datos",$usuario,$password)
Nuestro propsito es ir desarrollando, de forma simultnea, ejemplos con ambas bases de datos. Eso no requerir manejar, en paralelo, objetos de ambos tipos. Para facilitar un poco las cosas,en el ejemplo siguiente veremos como unificar en una sola funcin los procesos de conexin a ambas bases de datos. De esa forma, modificando un solo parmetro, podramos crear indistintamente objetos de uno u otro tipo.
<?php function conecta($base,$tipo){ if ($tipo=='MySQL'){ $db = new PDO('mysql:host=localhost','pepe','pepa'); /* crea la base de datos si no existe */ $db->query("CREATE DATABASE IF NOT EXISTS ".$base); /* crea un nuevo objeto usando la base de datos pasada como parmetro sin riesgo de error por inexistencia de la base */ if($db1 = new PDO('mysql:host=localhost;dbname='.$base,'pepe','pepa')){ print "Creado o abierta la base de datos MySQL: ".$base.'<br />'; return($db1); } else { print "Error: No puede conectarse con la base de datos.<br />"; print "<br />".$db1->errorInfo()."<br />"; exit(); } } if ($tipo=='SQLite'){ if ($db = new PDO('sqlite:'.$base)){ print "Creado o abierto el fichero SqLite: ".$base.'<br />'; return($db); } else { print "Error: No puede conectarse con la base de datos.<br />"; print "<br />".$db->errorInfo()."<br />"; exit(); } } } /* Hacemos una llamada a esta funcin pasndole como parmetros nombre de la base de datos y tipo*/ $dbDual= conecta('practicar','MySQL'); ?>
Caso MySQL Caso SQLite
<?php /* borramos las bases de datos creadas en el ejemplo anterior */ unlink('./images/baseSQLite.zpq'); unlink('practicar'); ?>
ejemplo486.php
Cuidado!
SQLite ignora los valores que se trate de asignar al tamao del campo. SQLite no impone ninguna limitacin en el 9 tamao de un campo siempre que no sobrepase el valor mximo preestablecido que est establecido en 10 bytes.
Quiere esto decir que podramos permitirnos la frivolidad de definir un tipo de campo como tipo paraguas. Las reglas de afinidadanteriores lo convertiran de forma automtica en NUMERIC dado que no contiene ninguna de las cadenas indicadas en las reglas anteriores. Esta peculiaridad de SQLite resulta muy til cuando se trata de compatibilizar su sintaxis con la de otros gestores de bases de datos ms estrictas en cuanto a su sintaxis. En ejemplos posteriores veremos como SQLite es capaz de manejar, sin apenas modificaciones, definciones de tablas propias de MySQL. Esta tabla es un resumen de las afinidades de tipos entre las definiciones de los gestores ms habituales y SQLite.
Nombres comunes en SQL utilizables en la declaracin de tipos INT, INTEGER, TINYINT, SMALLINT, MEDIUMINT, BIGINT, UNSIGNED BIG INT, INT2 ,INT8 CHARACTER(20), VARCHAR(255), VARYING CHARACTER(255), NCHAR(55), NATIVE CHARACTER(70), NVARCHAR(100), TEXT, CLOB BLOB (sin especificar tipos de datos) REAL, DOUBLE, DOUBLE PRECISION, FLOAT NUMERIC, DECIMAL(10,5), BOOLEAN, DATE, DATETIME Afinidad INTEGER TEXT NONE REAL NUMERIC Regla 1 2 3 4 5
La flexibilidad de SQLite an tiene un nuevo aspecto diferencial. Qu puede ocurrir si tratamos de agregar datos alfanumricos a un campo definido como NUMERIC? SQLite intentar adecuar los contenidos de los campos a la forma de establecimiento establecida en la definicin de tabla y/o las reglas de afinidad y cuando esto no resulta posible adeca la forma de almacenamiento a los contenidos. En la tabla tienes descritas algunas situaciones en las que se producen adaptaciones de este tipo.
Afinidad TEXT Comportamiento Un campo con afinidad TEXT almacena todos los datos utilizando las formas NULL, TEXT o BLOB. Si se inserta un dato numrico en un campo con afinidad TEXT ser convertido en cadena antes de ser almacenado Un campo con afinidad NUMERIC puede contener valores de cualquiera de las cinco clases de almacenamiento. Cuando se insertan textos la clase de almacenamiento del texto el campo intenta convertirse a INTEGER o REAL (en orden de preferencia). Realiza esa transformacin si se conservan los 15 primeros dgitos significativos del nmero (conversin sin prdidas y reversible). Si la conversin sin prdida no es posible, entonces el valor se almacena con la clase de almacenamiento TEXT. No se intenta convertir los valores NULL o BLOB. Una cadena con aspecto de punto flotante con un punto decimal o notacin exponencial,que pueda ser expresada como un entero ser convertida en entero. Por ejemplo, la cadena 3 .0 e +5 se almacena en una columna con afinidad NUMERIC con el valor 300.000, no como el valor de punto flotante 300.000,0. Una columna que utiliza afinidad INTEGER se comporta igual que una columna con afinidad NUMRICO. La diferencia entre la afinidad INTEGER y NUMERIC slo es evidente en una expresin de conversin Un campo con afinidad REAL se igual que con afinidad NUMERIC excepto que fuerza valores enteros en la representacin de punto flotante. Los valores de punto flotante sin ningn componente fraccionaria (por ejemplo 23.0) se escriben en el disco como enteros con el fin de ocupar menos espacio. Cuando son leidos recuperan su condicin de punto flotante. Una columna con afinidad NONE no establece ninguna preferencia de clase de almacenamiento.
NUMERIC
INTEGER
REAL NONE
Creacin de tablas
La creacin de tablas SQLite, tiene una sintaxis prcticamente igual a la utilizada por MySQL. Requiere una de estas dos sentencias CREATE TABLE IF NOT EXISTS tabla (campo1, campo2,... ) o CREATE TABLE tabla (campo1, campo2,... ) La nica diferencia entre ambas opciones es que la segunda dara un error si tratramos de crear una tabla preexistente mientras que la primera no da ese mensaje de error. La definicin de los campos es mucho menos estricta que en MySQL. Sera suficiente con asignarles un nombre sin tan siquiera declarar un tipo. La declaracin de tipos, si se opta por hacerla, tiene la amplitud comentada en prrafos anteriores respecto a las afinidades y los parmetros restrictivos los llambamos flags de campo en MySQL tienen como all carcter opcional y, tal como indicamos un poco ms arriba, son bsicamente los mismos que MySQL con las excepciones ya comentadas. La ejecucin de las sentencias SQLite por medio de la clase PDO requiere utilizar el mtodo siguiente: $resultado=$objeto->query(sentencia) dnde $resultado puede recoger un valor booleano (que confirmara la correcta ejecucin de la sentencia o los eventuales errores producidos durante la ejecucin de la misma) o el objeto con el resultado de la ejecucin de dicha sentencia (una consulta, por ejemplo).
Las diferencias sintcticas en la definicin de la tabla de ambos tipos de base de datos (MySQL y SQLite) son las que tienes resumidas en esta tabla:
Diferencias de sintaxis en definicin de tablas MySQL SQLite
Contador TINYINT(8) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT Contador INTEGER PRIMARY KEY AUTOINCREMENT
SQLite no admite ni ZEROFILL ni UNSIGNED. Los campos auticrementales en SQLite tienen que ser definidos obligatoriamente como: INTEGER PRIMARY KEY AUTOINCREMENT MySQL SQLite
DNI CHAR(8) NOT NULL DNI CHAR(8) NOT NULL UNIQUE Sexo Enum('M','F') DEFAULT 'M' not null Sexo VARCHAR DEFAULT 'M' not null
Los indices nicos se definen en SQLite incluyendo la palabra UNIQUE como un flag en la definicin del campo. MySQL SQLite
SQLite no permite campos del tipo Enum. Por esa razon lo convertimos en VARCHAR. Ya buscar SQLite las afinidades de esta palabra. En cualquier caso no va a presentarnos demasiados problemas. Bastara con utilizar algn recurso de PHP para restringir el contenido de ese campo a un valor 'M' o 'F'. MySQL SQLite
Tampoco estn permitidos en SQLite los campos tipo SET. Lo sustituimos por VARCHAR. Por cuestin de compatibilidad entre ambas tablas optamos por hacer de este mismo tipo, VARCHAR, el campo Idiomas de la tabla MySQL. Dado que este tipo va a recoger un nmero en la tabla siempre ser posible emular su comportamiento incluyendo una funcin PHP que interprete ese valor MySQL SQLite En SQLite las claves primarias, nicas e indices se incluyen en la propia definicin del campo. Por lo tanto esta lnea no es requerida. MySQL SQLite En SQLite las claves primarias, nicas e indices se incluyen en la propia definicin del campo. Por lo tanto esta lnea no es requerida. MySQL SQLite La definicin de tipo de tabla es exclusiva de MySQL. Cuando se trata de SQLite no se requiere esa definicin
PRIMARY KEY(DNI)
type=MyISAM
Respetando las exigencias comentadas en la tabla anterior hemos creado este script mediante el cual construiremos dos tablas de caractersticas bastante similares.
<?php include('conecta.inc.php'); /* Hacemos dos llamada a esta funcin conecta incluida en el fichero conecta.inc.php como parmetros nombre de la base de datos y tipo. Creamos dos objetos, uno para MySQL y en la otra el SQLite */ $dbMySQL= conecta('ejemploSQLite','MySQL'); $dbSQLite= conecta('ejemploSQLite','SQLite'); /* asignamos a la variable tabla en nombre de la nueva tabla */ $tabla='demo4'; /* transcribimos el cdigo del ejemplo 379 */ $crear="CREATE TABLE IF NOT EXISTS $tabla ("; $crear.="Contador TINYINT(8) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,"; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; $crear.="Nacimiento DATE DEFAULT '1970-12-21', "; $crear.="Hora TIME DEFAULT '00:00:00', "; $crear.="Sexo Enum('M','F') DEFAULT 'M' not null, "; $crear.="Fumador CHAR(0) , ";
$crear.="Idiomas SET(' Castellano',' Francs','Ingls',' Alemn',' Blgaro',' Chino'), "; $crear.=" PRIMARY KEY(DNI), "; $crear.=" UNIQUE auto (Contador)"; $crear.=")type=MyISAM"; $crear1="CREATE TABLE IF NOT EXISTS $tabla ("; $crear1.="Contador INTEGER PRIMARY KEY AUTOINCREMENT,"; $crear1.="DNI CHAR(8) NOT NULL UNIQUE, "; $crear1.="Nombre VARCHAR (20) NOT NULL, "; $crear1.="Apellido1 VARCHAR (15) not null, "; $crear1.="Apellido2 VARCHAR (15) not null, "; $crear1.="Nacimiento DATE DEFAULT '1970-12-21', "; $crear1.="Hora TIME DEFAULT '00:00:00', "; $crear1.="Sexo VARCHAR DEFAULT 'M' not null, "; $crear1.="Fumador CHAR(0) , "; $crear1.="Idiomas VARCHAR "; $crear1.=")";
/* realizamos la consulta de creacin en ambas bases de datos*/ if($dbSQLite->query($crear1)){ print "La tabla SQLite $tabla ha sido CREADA<br>"; } else{ print "Ha habido un error de PDO: <br />" ; echo "<pre>"; print_r($dbSQLite->errorInfo()); echo "</pre>"; } /* repetimos el mismo proceso ahora con la base de datos MySQL */ if($dbMySQL->query($crear)){ print "La tabla MySQL $tabla ha sido CREADA<br>"; } else{ print "Ha habido un error de PDO: <br />" ; echo "<pre>"; print_r($dbSQLite->errorInfo()); echo "</pre>"; } ?>
dnde tabla es el nombre de la tabla, campo1, campo2, etc. son los nombres de los campos y valor1, valor2, etc. son los valores a incluir en cada uno de los campos. La nica diferencia entre esta sentencia y la equivalente de MySQL es que aqu la palabra INTO tiene carcter obligatorio mientras que all solo es opcional.
Aadir un registro
Igual que ocurra en el caso de MySQL tambin aqu puede aadirse un registro incluyendo los valores en la propia sentencia o recogindolos de variables PHP previamente definidas.
En este ejemplo, dual como todos los siguientes, se agrega a la tabla demo4 de dos bases de datos distintas SQLite y MySQL cuyo nombre es ejemploSQLite un registro cuyos valores son:
DNI Nombre Apellido1 Apellido2 Nacimiento Sexo Hora Fumador Idiomas
16:24:52 null
Presta atencin a los siguientes aspectos: En la sentencia no se alude al campo Contador. La razn es que se trata un campo AUTOINCREMENTAL y en ese tipo de campos los valores de los registros se escriben automticamente cada vez que se aade uno nuevo. El registro no se aadira si el valor de DNI coincidiera con otra ya existente en la tabla. Recuerda que habamos definido ese campo como ndice primario. Si no hubiramos incluido el aviso de error no tendramos ninguna referencia sobre el xito de la insercin y no detectaramos el problema de duplicidad. Sencillamente ocurrira que el registro no se aadira pero no nos enteraramos de tal circunstancia. En el tratamiendo del campo Fumador definido en MySQL con longitud cero y que solo permite como valores NULL o una cadena vaca es vlido todo lo comentado en esta pgina. Lo transcribimos literalmente un poco ms abajo. El error PDO generado al producirse una coincidencia de valores en un campo nico tiene el cdigo 19. En este ejemplo puedes la manera de utilizarlo para depurar el mensaje de advertencia.
Ver cdigo fuente
Quiz te resulten de alguna utilidad estos comentarios: Observa en el cdigo fuente que al insertar las variables en los VALUES de la sentencia MySQL ponemos cuando se trata de valores tipo cadena '$variable' (el nombre de la variable entre comillas) y cuando se trata de valores nmericos sin comillas. Si quieres introducir el valor NULL en un campo tipo VAR(0) define la variable as: $variable="NULL" y si quieres introducir unacadena vaca defnela de este otro modo:$var="''" -comillas dobles (") seguidas de dos comillas sencillas (') y para terminar otras comillas dobles (") y cuando hagas alusin a esa esta variable como un VALUE en la sentencia de insercin no la pongas entre comillas.
La consulta ms simple
Si utilizamos la sentencia SELECT * FROM tabla obtendremos informacin sobre todos los campos (*) y la salida estar en el mismo orden en el que fueron aadidos los datos. Si visualizas este ejemplo, vers que aparecen ordenados por el valor autonumrico del campo Contador lo cual, como ves, resulta coherente con la afirmacin anterior. La nica diferencia entre los resultados de la misma consulta en ambas bases de datos estara en la presentacin del campo autonmerico. En el caso de MySQL aparece con ceros a la izquierda dado que al definir la tabla establecimos TINYINT(8) UNSIGNED ZEROFILL mientras que en caso de SQLite estuvimos obligados configurar ese campo autoincremental como INTEGER PRIMARY KEY. Si observas el cdigo fuente, en el caso del campo Idioma hemos tenido que hacer un pequeo arreglo en la consulta SQLite para visualizar los mismos datos que en MySQL. La razn es la no admisin de campos tipo SET ni ENUM por parte de SQLite.
Ejecutar consulta Ver cdigo fuente
Cuidado! En los comentarios contenidos en estos ejemplos puedes ver la forma en la que mysql_fetch_row ymysql_fetch_array tratan los ndices escalares de los resultados que producen los SELECT de MySQL. Los valores de los ndices se asignan a los contenidos de los campos por el mismo orden en el que estos se escriben en la sentencia SELECT. El campo1 (primero que se escribe) ser recogido por el elemento de ndice cero del array, el campo2 ser recogido con ndice uno y as sucesivamente
Consultas condicionadas
La clasula WHERE permite un variado abanico de condiciones, que trataremos de resumir aqu. Las opciones sealadas con (*) tiene alguna diferencia de comportamiento. En el propio ejemplo o en llamada a pie de tabla tienes comentadas sus causas.
Operador Tipo Sintaxis Descripcin Cdigo Ver
de campo
fuente ejemplo Selecciona los registros que contienen en el campo un valor igual a num Selecciona los registros que contienen en el campo una cadena idntica a cadena (*) Selecciona los registros que contienen en el campo un valor menor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmenores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**) Selecciona los registros que contienen en el campo un valor menor O igual a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmenores que los de la cadena, siendo n el nmero de caracteres que contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo un valor mayor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmayores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**) Ver Ver Ver Ver Ver Probar Probar Probar Probar Probar
Numrico WHEREcampo<=num
Cadena
WHEREcampo<="cadena"
Ver
Probar
Ver Ver
Numrico WHEREcampo>=num
Selecciona los registros que contienen en el campo un valor mayor o igual a num Ver Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres sonmayores que los de la cadena, siendo n el nmero de caracteres que contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo valores que coinciden con alguno de los especificados dentro del parntesis. Cuando se trata de valores no numricoz han de ir entre comillas
Cadena
WHEREcampo>="cadena"
Ver
Probar
IN
Ver
Probar
Selecciona los registros en los que los valores contenidos en el campo seleccionado estn comprendidos en el intervalo valor1 (mnimo) valor2 (mximo) incluyendo en la seleccin ambos extremos. Ver Cuando los contenidos de los campos son cadenas sigue los mismos criterios que se indican para los dems operadores de comparacin Selecciona los registros en los que los valores contenidos en el campo seleccionado son NULOS Selecciona los registros en los que los valores contenidos en el campo seleccionado son NO NULOS Ver Ver
Probar
Cadena Cadena
Probar Probar
(*) Cuando se trata de cadenas de caracteres, el concepto menor que significa anterior en la ordenacin de los caracteres segn su cdigo ASCII y mayor quesignifica posterior en esa misma ordenacin. (**) La discriminacin de Maysculas/Minsculas depender del tipo de campo. Recuerda que en MySQL los tipo BLOB hacen esa discriminacin, mientras que los de tipo TEXT son insensibles a maysculas/Minsculas y tambin a vocales con y sin tilde. SQLite siempre toma en consideracin esas diferencias.
Cuando se trata de comparar cadenas MySQL dispone de una potente instruccin (LIKE) que permite establecer los criterios de seleccin a toda o parte de la cadena. Su sintaxis contempla distintas posibilidades utilizando dos comodines>: % (que se comporta de forma similar al (*) en las bsquedas de Windows) y _ (de comportamiento similar a (?) en Windows). Aqu tienes algunas de sus posibilidades:
Cdigo Ver fuente ejemplo Ver Ver Ver Ver Probar Probar Probar Probar
Sintaxis WHERE campoLIKE '%cadena%' WHERE campoLIKE 'cadena%' WHERE campoLIKE '%cadena' WHERE campoLIKE '_cadena%'
Descripcin Selecciona todos los registros que contengan la cadena en el campo indicado sea cual fuere su posicin Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente al principio del campo Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente al final del campo Selecciona todos los registros en los que el primer caracter del campo puede ser cualquiera pero los siguientes han de serexactamente los indicados en cadena pudiendo ir seguidos de cualesquiera otros caracteres
El comodn (_) puede ir tanto al principio como al final y puede repetirse tantas veces como sea necesario. Por tanto sera correctoLIKE '___es%' y tambin LIKE 'a___es%' as como: LIKE '%a___es'.
La clasula WHERE aun tiene ms opciones. Acepta mltiples condiciones vinculadas por los operadores lgicos AND, OR, NOT o sus sintaxis equivalentes: &&, || y !. El comportamiento de estos operadores es idntico al descrito para sus homnimos de PHP en esta pgina
Observa que en el cdigo fuente hemos incluido dos consultas distintas y que la consulta MySQL devuelve un valor ms que SQLite. Se debe a que la funcin STDDEV (desviacin tpica de la poblacin) no est definida en SQLite.
Es vlido el comentario del caso anterior para STDDEV (desviacin tpica de la poblacin) que no est definida en SQLite.
DATE_FORMAT(Nacimiento,'%d') Ver DATE_FORMAT(Nacimiento,'%e') Ver DATE_FORMAT(Nacimiento,'%m') Ver DATE_FORMAT(Nacimiento,'%y') Ver DATE_FORMAT(Nacimiento,'%Y') Ver
Supongamos tambin, que la seleccin va a constar de tres pruebas que sern juzgadas y calificadas por tres tribunales distintos. Una primera opcin sera crear tres tablas una para cada tribunal e incluir en ellas todos los datos de cada uno de los individuos. Esa opcin es factible pero no es ni la ms cmoda, ni tampoco es la ms rpida ni la que menos espacio de almacenamiento necesita. No debemos olvidar que una tabla puede tener una enorme cantidad de registros. Una opcin alternativa sera crear tres nuevas tablas que slo contuvieran dos campos cada una. Por ejemplo el campo DNI y el campo Calificacin. Como quiera que el campo DNI ha de contener los mismos valores en las cuatro tablas y adems es un campo nicopodran crearse las nuevas tablas y luego copiar en cada una de ellas todos los DNI de la tabla original. Nos garantizara que no habra errores en los DNI y adems nos garantizara que se incluyeran todos los aspirantes en esas nuevas tablas. Aqu tienes el cdigo fuente de un script que crea esas tres tablas (a las que hemos llamado prueba1, prueba2 y prueba3.
Ver cdigo fuente
en la que, como ves, modificamos ligeramente la sintaxis ya que anteponemos el nombre de la tabla al del campo correspondiente separando ambos nombres por un punto, con lo cual no hay posibilidad de error de identificacin del campo incluso cuando campos de distinta tabla tengan el mismo nombre. Otra innovacin -respecto a los ejemplos anteriores- es que detrs de la clusula FROM escribimos los nombres de todas las tablas que est usando SELECT. A partir de ah se pueden establecer todo tipo de relaciones para las sentencias WHERE, ORDER BY y GROUP BY utilizando para ellocampos de cualquiera de las tablas sin otra particularidad ms que poner cuidado al aludir a los campos utilizando siempre la sintaxisnombre_tabla.nombre_campo. A modo de ejemplo hemos procurado comentarlo lnea a lnea aqu tienes un script PHP que hace una consulta conjunta de las tablasdemo4, demodat1, demodat2 y demodat3 y nos presenta una tabla con los datos personales y las puntuaciones de las tres pruebas as como las suma de puntos de las tres y, adems, ordena los resultados -de mayor a menor- segn la suma de las tres puntuaciones.
Ejecutar consulta Ver cdigo fuente
$recuento=$actuacion-> rowCount() Tambin rowCount es un mtodo propio de los objetos resultantes de una $actuacion . La variable recuento contiene el nmero de registros afectados por la ejecucin de esa sentencia. Cuando se trata de sentencias que devuelven resultados (caso tpico de las consultas) pueden utilizarse algunos mtodos que facilitan la organizacin de la informacin. Los ms tiles pueden ser estos: $resultado=$actuacion-> fetch(PDO::FETCH_NUM ) aplicando el mtodo fetch al objeto que resulta de execute ($actuacion) se recoge el $resultado en un array escalar cuyo primer ndice es cero y que sigue el mismo orden por el que los campos han sido incluidos en la consulta en el registro actual. $resultado=$actuacion-> fetch(PDO::FETCH_ASSOC ) Cuando se incluye FETCH_ASSOC el resultado ser un array asociativo cuyos ndices coinciden con los nombres de los campos incluidos en la consulta en el registro actual. $resultado=$actuacion-> fetch(PDO::FETCH_BOTH ) FETCH_BOTH es el valor por defecto. Devuelve un array asociativo indexado por los nombres de los campos y otro escalar indexado (a partir de cero) por las posiciones de los campos en la sentencia SELECT en el registro actual. $resultado=$actuacion-> fetchAll(PDO::FETCH_BOTH )
Hay que modificar el mtodo fetch agregando el siguiente parmetro: $resultado=$actuacion-> fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT ) de esta forma ya estaremos en condiciones de construir esa consulta y efectuar la lectura de los resutados por medio de un bucle tal como puedes ver en este ejemplo.
<?php include('conecta.inc.php'); $dbMySQL= conecta('ejemploSQLite','MySQL'); $dbSQLite= conecta('ejemploSQLite','SQLite'); $tabla="demo4"; $query= "SELECT Nombre, Apellido1, Apellido2 FROM $tabla WHERE Nombre='Dorotea'"; /* preparamos la consulta*/ $consulta=$dbSQLite->prepare($query); /* ejecutamos la consulta */ $consulta->execute(); print "<br><br>La consulta SQLite ha producido los siguientes resultados<br><br>"; /* creamos un bucle que ir recorriendo los resultados de la consulta como consecuencia de haber agregado a fecth el valor PDO::FETCH_ORI_NEXT */ while($resultado=$consulta->fetch(PDO::FETCH_ASSOC,PDO::FETCH_ORI_NEXT)){ print $resultado['Apellido1']." ".$resultado['Nombre']."<br />"; } /* repetimos el mismo proceso anterior, esta vez para el objeto MySQL */ $consulta=$dbMySQL->prepare($query); $consulta->execute(); print "<br><br>La consulta MySQL ha producido los siguientes resultados<br><br>"; while($resultado=$consulta->fetch(PDO::FETCH_ASSOC,PDO::FETCH_ORI_NEXT)){ print $resultado['Apellido1']." ".$resultado['Nombre']."<br />";
} ?>
Realizar consultas
Otra posibilidad, alternativa a la anterior, nos la ofrece el siguiente mtodo PDO: $resultado=$actuacion-> fetchAll() dnde $resultado es un array bidimensional que contiene el resultado de la ejecucin de una sentencia previamente preparada mediante $actuacion=$objeto->prepare(SENTENCIA) y ejecutada por medio de $actuacion->execute(). El primer ndice del array es de tipo escalar (contiene el nmero de orden, empezando en cero, de cada registro ledo) El segundo ndice ofrece dos posibilidades. Una de carcter escalar (siendo su valor el nmero de orden, partiendo de cero, del nombre del campo en la sentencia que crea la consulta) y otra asociativa siendo el nombre del ndice identico a nombre del campo o campos sobre los que se realiza la consulta.
<?php include('conecta.inc.php'); $dbMySQL= conecta('ejemploSQLite','MySQL'); $dbSQLite= conecta('ejemploSQLite','SQLite'); $tabla="demo4"; $query= "SELECT Nombre, Apellido1, Apellido2 FROM $tabla WHERE Nombre='Dorotea'"; /* preparamos y ejecutamos la consulta */ $consulta=$dbSQLite->prepare($query); $consulta->execute(); print "<br><br>La consulta SQLite ha producido los siguientes resultados<br><br>"; /* mediante fetchall nos devolver un array bidimensional con todos los resultados*/ $resultado=$consulta->fetchAll(); /* el bucle nos recorrer los primeros indices y extraeremos los valores de los elementos deseados de cada uno de esos indices */ for ($i=0;$i<sizeof($resultado);$i++){ print $resultado[$i]['Nombre']." ".$resultado[$i]['Apellido1']."<br>"; } /* repetimos la misma consulta ahora con el objeto MYSQL*/ $consulta=$dbMySQL->prepare($query); $consulta->execute(); print "<br><br>La consulta MySQL ha producido los siguientes resultados<br><br>"; $resultado=$consulta->fetchAll(); for ($i=0;$i<sizeof($resultado);$i++){ print $resultado[$i]['Nombre']." ".$resultado[$i]['Apellido1']."<br>"; } ?>
Realizar consultas
La tabla sqlite_master
Auque en algunas situaciones puntuales las transacciones de las que hablaremos ms adelante ser necesario el uso de un fichero temporal llamado rollback journal, la gestin de una base de datos SQLite puede hacerse mediante un nico archivo llamado archivo principal de la base de datos. Ese archivo principal est formado varias por partes iguales, llamadas pginas, de tamaos comprendidos entre 512 y 65536 31 bytes. El nmero de pginas mximo puede ser 2 - 2 lo cual significa que un fichero de base de datos SQLite podra llegar a tener (considerando todas las pginas posibles y el tamao mximo de estas) una dimensin de 140 terabytes. En la seccin de encabezado del archivo principal de base de datos est la tabla sqlite_master, gestionada de forma automtica, que contiene la informacin sobre la ubicacin de las restantes tablas (nmero de pgina en el que estn situadas), ndices, view y trigger contenidos en la base de datos. Se crea de forma automtica mediante una sentencia similar a esta:
CREATE TABLE sqlite_master( type text, name text, tbl_name text, rootpage integer, sql text )
En ella, el campo type de esta tabla recoge, dependiendo del tipo de objeto utilizado, uno de los siguientes valores: 'table', 'index', 'view'o 'trigger'. El campo name contendr el nombre del elemento(indice, consulta, trigger o tabla). En tbl_name se recoge el nombre de la tabla a la que est asociado el objeto (si el elemento es un ndice sera el nombre de la tabla a la que va asociado). Por ltimo, en rootpage se indica el nmero de pgina en la que comienza el objeto y el campo de texto sql suele incluir el texto de la sentencia utilizada para la creacin del objeto. Todas las tablas de una base de datos SQLite, estn registradas en sqlite_master. Una consulta como esta nos permite visualizar su contenido.
<?php include('conecta.inc.php'); $dbSQLite= conecta('ejemploSQLite','SQLite'); /* Escribimos una consulta todos los datos de la tabla correspondiente a registros tipo table */ $llamadaSQLite = "SELECT * FROM sqlite_master WHERE type='table'"; if($resultado=$dbSQLite->query($llamadaSQLite)){ print "La tabla sqlite_master contiene los siguientes registros <br>"; foreach ($resultado as $registro=>$contenido){ print "<b>Tabla del registro n.: ".$registro."</b><br />"; foreach ($contenido as $campo=>$valor){ if (!is_int($campo)){ print "<i>Campo: </i>".$campo; print "<i> Valor: </i>".$valor."<br>"; } } } } else{ print "Ha habido un error de PDO: <br />" ; echo "<pre>"; print_r($dbSQLite->errorInfo()); echo "</pre>"; } ?>
ejemplo529.php
Si ejecutas el ejemplo anterior tal vez te encuentres con una tabla llamada sqlite_sequence en cuya estructura existen nicamente dos campos: name y seq. Esta tabla de crea de forma automtica cuando alguna de las tablas que componen la base de datos incluye un campo autoincremental. Ser en esta tabla donde se recogan los ltimos valores de estos campos en cada una de las tablas que los requieran.
3. Eliminar la tabla antigua. 4. Cambiar el nombre a la nueva tabla asignndole el de la recin borrada.
Cuidado!
Hay que tener muy presente que con esta sentencia en la que no aparece WHERE se modificarn TODOS LOS REGISTROS DE LA TABLA y por lo tanto los campos modificados tendrn el mismo valor en todos los registros.
Tal como puedes ver, en el ejemplo utilizamos una preparacin declarada (prepare statement) como procedimiento alternativo para modificar la calificacin anterior y pasar a SIETE puntos la nota en todos los registros.
<?php /* incluimos la funcion conecta y creamos objetos de ambas bases de datos */ include('conecta.inc.php'); $dbMySQL= conecta('ejemploSQLite','MySQL'); $dbSQLite= conecta('ejemploSQLite','SQLite'); /* escribimos la consulta que actualizar a 7 el campo Puntos de la tabla prueba1 */ $consulta = "UPDATE prueba1 SET Puntos=7"; /*preparamos la consulta de la tabla SQLite*/ $actualiza = $dbSQLite->prepare($consulta); /* aplicamos el mtodo execute al objeto creado por el mtodo anterior */ $actualiza->execute(); /* leemos el numero de registros afectados por la ejecucin de la sentencia */ $numero_resultados = $actualiza->rowCount(); /* visualizamos la informacin del resultado */ print("Se han actualizado $numero_resultados registros"); /* repetimos exactamente el proceso anterior preparando un objeto MySQL*/ $actualiza = $dbMySQL->prepare($consulta); $actualiza->execute(); $numero_resultados = $actualiza->rowCount(); print("Se han actualizado $numero_resultados registros"); ?>
Ejecutar la modificacin
Hecho este inciso continuaremos con la referencia al borrado de registros. En este ejemplo, tienes el cdigo fuente de un script que realiza el borrado de un registo mediante un formulario en el que se inserta el DNI tanto en la tabla demo4 como demodat1, demodat2 y demodat3 manteniendo la integridad referencial entre los cuatro ficheros.
Eliminar un aspirante Ver cdigo formulario Ver cdigo script
Indica a SQLite que en ese punto comienza una transaccin. Todas las sentencias que se ejecuten a partir de ella tendrn carcterprovisional y no se concretarn de forma efectiva hasta que encuentre una sentencia que las confirme. $objeto->query("ROLLBACK") Mediante esta sentencia advertimos a SQLite que finaliza la transaccin pero que no debe hacerse efectiva ninguna de las modificaciones incluidas en ella. $objeto->query("COMMIT") Esta sentencia advierte a SQLite que ha finalizado la transaccin y que S debe hacer efectivos todos los cambios incluidos en ella.
Ejecutar ejemplo Ver cdigo fuente
<?php include('conecta.inc.php'); $dbMySQL= conecta('ejemploSQLite','MySQL'); $dbSQLite= conecta('ejemploSQLite','SQLite'); $nombre="' or '34=34"; $tabla="demo4"; /* recogemos la cadena tal como viene en la condicin WHERE. Por tratarse de una cadena tenemos que entrecomillar el nombre de la variable en esa clusula */ $query= "SELECT Nombre, Apellido1, Apellido2 FROM $tabla WHERE Nombre='$nombre'"; /* esta consulta nos dar como resultado una lista de todos los registros de la tabla. Habremos vulnerado las mnimas reglas de seguridad */ /* primero con el objeto SQLite */ print "Esta es la condicin de la consulta: ".$query."<br />"; print "<br /><i>Resultado de la consulta SQLite</i><br />"; if($resultado=$dbSQLite->query($query)){ print "Estos son los resultados de la consulta en la base de /><br />"; foreach ($resultado as $matriz){ print $matriz[1]." ".$matriz[2].", ".$matriz[0]."<br } } /* Igual proceso el objeto MySQL */ print "<br /><i>Resultado de la consulta MySQL</i><br />"; if($resultado=$dbMySQL->query($query)){ print "Estos son los resultados de la consulta en la base de /><br />"; foreach ($resultado as $matriz){ print $matriz[1]." ".$matriz[2].", ".$matriz[0]."<br } } ?>
Ver ejemplo
Como habrs podido observar una consulta con el cdigo adecuado WHERE Nombre='' or '34=34' muestra la vulnerabilidad y devuelve todos los registros contenidos en la tabla por las mismas razones ya comentadas al estudiar MySQL. PDO dispone de un mtodo que pala en gran medida este tipo de riesgos. Se trata de: $variable=$objeto->quote(cadena) que recoge en $variable el contenido de la cadena incluyndolo dentro de unas comillas simples'. De esa forma una cadena como ' or '34=34 resultara transformada en '' or '34=34'
/* aplicamos el mtodo quote a la cadena con lo cual el nuevo valor de la variable \$nombre se entrecomillar de forma automatica */ $nombre=$dbSQLite->quote($nombre); $tabla="demo4"; /* ya no incluimos la variable \$nombre entre comillas. Ya se las ha asignado el mtodo quote */ $query= "SELECT Nombre, Apellido1, Apellido2 FROM $tabla WHERE Nombre=$nombre"; print "Esta es la condicin de la consulta: ".$query."<br />"; /* la consulta ahora ya no listar ninguno de los registros. Habremos mejorado la seguridad */ print "<br /><i>Resultado de la consulta SQLite</i><br />"; if($resultado=$dbSQLite->query($query)){ print "Estos son los resultados de la consulta en la base de datos SQLite<br /><br />"; foreach ($resultado as $matriz){ print $matriz[1]." ".$matriz[2].", ".$matriz[0]."<br />"; } } /* tambien en le caso de MySQL se producir el resultado esperado */ print "<br /><i>Resultado de la consulta MySQL</i><br />"; if($resultado=$dbMySQL->query($query)){ print "Estos son los resultados de la consulta en la base de datos SQLite<br /><br />"; foreach ($resultado as $matriz){ print $matriz[1]." ".$matriz[2].", ".$matriz[0]."<br />"; } } ?>
Ver ejemplo
En cualquier caso los procedimientos anteriores no son los ms aconsejables para la realizacin de consultas seguras. Lo aconsejable en estos casos es utilizar las declaraciones preparadas agregando algunas opciones a las ya comentadas. A la sintaxis ya conocida: $actuacion= $objeto->prepare(SENTENCIA) $actuacion-> execute() puede hacrsele una modificacin incluyendo un nuevo mtodo (bindParam) que tiene como finalidad enlazar el valor de una variable con un identificador incluido en la sentencia SQL. Una sintaxis como esta: $actuacion= $objeto->prepare('SELECT * FROM tabla WHERE (Nombre=? and Apellido1=?)') $actuacion-> bindParam(posicion, $variable,tipo, longitud); $actuacion-> execute() en la que hacemos las siguientes modificaciones: En la sentencia SQL sustituimos por ? lo que anteriormente eran nombres de variables (entre comillas por su condicin de cadenas alfanumricas) del tipo '$nombre' y '$apellido'. Agregamos tantas llamadas a mtodos bindParam como ? contiene la sentencia SQL incluida por mtodo prepare Las llamadas a los mtodos bindParam requieren dos parmetros obligatorios y permiten otros dos opcionales. El primero de ellos posicion indica la posicin en la sentencia SQL del ? al que alude. Las posiciones se cuentan a partir de uno y de izquierda a derecha. El sealado como $variable es el nombre de una variable previamente definida que contiene el valor que ha de sustituir al? aludido. Hemos de tener en cuenta que ha de incluirse siempre un nombre de variable y que si tratramos de sustituirlo por un cadena que contenga su valor se producir un error.
El parmetro tipo tiene carcter opcional e indicara el tipo de contenido de la variable. Puede tener como valoresPDO::PARAM_STR o PDO::PARAM_INT (sin comilla). En el primer caso indicara que la variable es de tipo cadena y en el segundo que es de tipo entero. Cuando el tipo es PDO::PARAM_STR puede incluirse longitud que indicara el nmero de caracteres de la cadena. El mtodo execute producira los resultados ya comentados. Veamos dos ejemplos. El primero de ellos utiliza el mtodo bindParam( mientras que el segundo no lo hace.
Con bindParam Ver cdigo fuente Sin bindParam Ver cdigo fuente
Como habrs podido observar el uso de bindParam impidi la inyeccin del cdigo maligno. Desde las pginas oficiales de PHP se recomienda utilizar este mtodo en la situaciones en la que se prevean riesgos de este tipo. El mtodo bindParam permite algunas modificaciones tales como estas: $actuacion= $objeto->prepare('SELECT * FROM tabla WHERE (Nombre=:campo_nombre and Apellido1=:campo_apellido) ') $actuacion-> bindParam(':campo_nombre' , $variable,tipo, longitud); $actuacion-> execute() Hemos sustituido cada ? de la sentencia SQL por una palabra cualquiera precedida de : y tambin el nmero de posicion (en la llamada al mtodo bindParam) por una cadena (fjate que va entre comillas) que incluye exactamente el mismo nombre con los : obligatorios incluido en la sentencia SQL. Puedes verlo en el ejemplo.
Ver nuevo ejemplo Ver cdigo fuente
An disponemos de otra posibilidad alternativa a la anterior. Sera esta: $actuacion= $objeto->prepare('SELECT * FROM tabla WHERE (Nombre=:campo_nombre and Apellido1=:campo_apellido) ') $actuacion-> execute(array(':campo_nombre'=>$variable)) En este caso hemos omitido la llamada al mtodo bindParam y cmo alternativa hemos incluido en la llamada al mtodo execute un array asociativo al que asignmos como ndices los palabras de la sentencia (siempre precedidas por los dos puntos) y como valor los nombres de la variable que los contiene. Si en la sentencia utilizramos ? el array habra de ser de tipo escalar. Puedes verlo en los ejemplos.
Ver nuevo ejemplo Ver cdigo fuente Ver nuevo ejemplo Ver cdigo fuente
Como habrs podido observar el filtro de seguridad ha funcionado en todos estos ejemplos. Los intentos de visualizar nombre mediante el cdigo ' or '34=34 han fracasado.
Mejoradas las opciones de depuracin Soporte para servidor empotrado Conocido el manejo de las bases de datos MySQL y el manejo de las mismas mediante PDO o la librera mysql la utilizacin de esta nueva opcin no va a plantearnos demasiadas dificultades. Lo iremos comprobando en los epgrafes siguientes.
sudo apt-get install php5-mysqli con lo cual, en cualquiera de los dos casos, una vez reiniciado el servidor la pgina http://localhost/info.php debera mostrarnos una informacin similar a esta:
MySQLi no es un servidor de bases de datos nuevo o distinto de MySQL. Es nicamente una extensin PHP para acceder a ese tipo de bases de datos. Por tanto, los elementos propios de MySQL: ficheros, tablas, tipos de datos, ndices y sentencias son exactamente los ya comentados en las pginas cuyos enlaces hemos incluido en este prrafo. Desarrollaremos todos los ejemplos atendiendo a la existencia de un fichero al que llamaremos mysqli.inc.php cuyo contenido es el siguiente:
dnde $conexion es el identificador de la conexin y host, usuario y contrasea los respectivos nombres del servidor, usuario y contrasea que estn recogidos en la variables incluidas en el fichero mysqli.inc.php al que hemos hecho alusin en prrafos anteriores. Cuando se trata de cerrar la conexin es necesaria ejecutar mysqli_close de forma similar a la ya conocida. Ahora deberemos escribir: mysqli_close($conexion)
dnde $objeto es el identificador de un nuevo objeto, y servidor, usuario y contrasea los respectivos nombres del servidor, usuario y contrasea que coinciden con las ya mencionadas variables incluidas en el fichero mysqli.inc.php. El cierre de la conexin requiere invocar el mtodo close() y por lo tanto escribir algo como: $objeto->close()
Si estamos utilizando objetos los eventuales cdigos de error de conexin y sus descripciones los obtendramos de las propiedades$objeto->mysqli_connect_errno y span class="cursiva1">$objeto->mysqli_connect_error. Podrs observar que, a diferencia del caso de programacin por procesos, aqu errorno y error no van seguidos de parntesis.
Mediante procesos Ver cdigo fuente Mediante objetos Ver cdigo fuente
en este ltimo supuesto evitaramos la generacin de errores como consecuencia de intentar crear ya base de datos preexistente.
Cuidado! Fjate en el orden en el que se incluyen los parmetros. En el caso de mysqli la funcin mysqli_query lleva como primer parmetro es el indentificador de conexin y la sentencia propiamente dicha se incluye en segundo lugar. Esto es justo lo inverso de lo utilizado cuando se trabaja con el interface mysql y la funcin mysql_query.
Cuando se trata de conocer los cdigos de error habra que utilizar mysqli_errno($conexion) o $objeto->errno dependiendo del mtodo de programacin que estemos utilizando. En estos ejemplos tienes los procesos de creacin de una base de datos y la gestin de esos errores.
Mediante procesos Ver cdigo fuente Mediante objetos Ver cdigo fuente
en este ltimo supuesto evitaramos la generacin de errores como consecuencia de intentar borrar una base de datos inexistente.
La mayora de los contenidos de esta pgina son pura transcripcin del contenido de esta otra. Hay algunas diferencias de tratamiento que sealaremos para facilitarte la opcin de comparacin de los diferentes interfaces MySQL permite usar diferentes tipos de tablas tales como: ISAM, MyISAM o InnoDB. Las tablas ISAM (Indexed Sequential Access Method) son las de formato ms antiguo. Estn limitadas a tamaos que no superen los 4 gigas y no permite copiar tablas entre mquinas con distinto sistema operativo. Las tablas MyISAM son el resultado de la evolucin de las anteriores adaptadas por MySQL durante mucho tiempo como el formato por defecto para sus servidores de bases de datos. En las versiones ms recientes de MySQL est cambiando es criterio y empiezan a verse versiones que incluyen InnoDB como formato por defecto. Las tablas del tipo InnoDB (desarrolladas por la compaa finlandesa InnoBase a la que deben su nombre) tienen una estructura distinta a la de MyISAM, ya que utilizan un slo archivo por tabla en ver de los tres habituales en los tipos anteriores. Incorporan dos de ventajas muy importantes: permiten realizar transacciones y definir reglas de integridad referencial. Hablaremos ms adelante de ello. La definicin de uno u otro formato (MyISAM o InnoDB) debe hacerse en el momento de la creacin de tabla y solo reguiere agregarType=MyISAM Type=InnoDB a la sentencia MySQL encargada de crearla.
Creacin de tablas
Las tablas son elementos de las base de datos. Por esa razn nos resultar imposible crear una tabla sin tener creada yseleccionada una base de datos. Es por eso que para la creacin de una tabla se necesitan los siguientes requisitos: Tener abierta una conexin con el servidor MySQL. Tener seleccionada una base de datos.
donde nombre_base_datos es el nombre de la base de datos (puede ser una cadena entrecomillada o el nombre de una variable previa que contenga ese nombre). En este ltimo caso, como es habitual, el nombre de la variable no llevara comillas. El segundo parmetro$conexion es el identificador de conexin. Es decir, la variable creada al establecer la conexin con MySQL. Este valor debe insertarse siempre. La razn es que MySQL permite mantener abiertas varias, de forma simultnea, varias conexiones (podramos manejar ms de un servidor de bases de datos) y en esas condiciones no pueden darse ambigedades respecto a la base que pretendemos usar. Tambin es conveniente tener muy presente que en este caso hay que diferenciar tambin mysqli_select_db de mysql_select_db(observa que se diferencian nicamente en una i). Este proceso puede simplicarse incluyendo el nombre de la base de datos como cuarto parmetro de la funcin mysqli_connect. Mediante esta opcin $conexion = mysqli_connect ( servidor, usuario, contrasea, nombre_base_datos) estaremos seleccionando la base de datos nombre_base_datos a la vez que establecemos la conexin. Si hemos optado por la programacin orientada a objetos la seleccin de la base de datos puede incluirse en la llamada al constructor de la clase. La forma de hacerlo es similar a esta:
donde tabla es una cadena que contiene el nombre de la tabla que pretendemos crear, dnde campo1, campo2, etc. son las definiciones de los campos que pretendemos que contenga la tabla y tipo puede ser MyISAM o InnoDB segn el tipo de tabla que queramos crear. La nica diferencia entre ambas opciones es que la segunda dara un error si tratramos de crear una tabla preexistente (deberamos recurrir al procedimiento que hemos visto cuando crebamos bases de datos) mientras que la primera no da ese mensaje de error.
Es una palabra cualquiera distinta para campo de la tabla y que normalmente suele elegirse aludiendo al contenido. Por ejemplo,fecha_nacimiento, nombre_del_perro, etctera. No va entre comillas nunca y MySQL diferencia maysculas/minsculas. Para utilizar como nombres de campo palabras reservadas del lenguaje MySQL por ejemplo, create debemos escribirlas entre ` `. Observa que no son comillas sino acentos graves. Lo ms aconsejable es evitar esta situacin. tipo y dimensiones
Los tipos de campos los hemos visto en la pgina anterior tienen que ajustarse a uno de los soportados por MYSQL. El tipo de campo se escribe a continuacin del nombre sin otra separacin que un espacio y requieren la sintaxis estricta correspondiente a cada tipo. Cuando se establezca una dimensin como parmetro opcional de un campo deben tenerse en cuenta algunos detalles: Su valor se escribe entre parntesis y se incluye despus del nombre del campo. Si en un campo numrico introdujramos valores que exceden los lmites, su valor no se registrara en la tabla sino el valor dellmite ms prximo correspondiente a ese tipo de campo.
Supongamos un campo tipo TINYINT que permite valores comprendidos entre -128 y 127. Si asignramos en uno de sus registros un valor igual a 234 se escribira en la tabla 127 (el lmite superior) y si ponemos -834 escribira el lmite inferior, es decir, -128. En caso de cadenas, si el valor introducido sobrepasara la longitud mxima permitida, la cadena sera recortada y nicamente se registrara el nmero mximo de caracteres permitidos. flags del campo ( son opcionales) Puede utilizarse cualquiera de los permitidos para cada tipo de campo. Puedes verlos encerrados, entre corchetes, al lado de cada tipo de campo. Cuando sea necesario incluirlo han de escribirse inmediatamente despus del nombre del campo o de la dimesin (en los casos en que se incluya).
<?php /* crearemos antes una variable que recoja toda la sentencia y ser luego cuando la ejecutemos Definiremos una varable llamada $crear e iremos aadiendo cosas */ # la primera parte de la instruccin es esta (espacio final incluido $crear="CREATE TABLE IF NOT EXISTS "; # aadiremos el nombre de la tabla que ser ejemplo1 # fijate en el punto (concatenador de cadenas) que permite # ir aadiendo a la cadena anterior $crear .="ejemplo1 "; #ahora pongamos el parntesis (con un espacio delante) #aunque el espacio tambin podra detrs de ejemplo1 $crear .="( "; # insertemos el primer campo y llamemoslo num1 # hagamoslo de tipo TINYINT sin otras especificamos # sabiendo que solo permitira valores numricos # comprendidos entre -128 y 127 $crear .="num1 TINYINT , "; # LOS CAMPOS SE SEPARAN CON COMAS por eso # la hemos incluido al final de la instruccin anterior # ahora num2 del mismo tipo con dimensin 3 y el flag UNSIGNED # Y ZEROFILL que: cambiar los lmites de valores # al intervalo 0 - 255, y rellenar con ceros por la izquierda # en el caso de que el nmero de cifras significativas # sea menor de 3. # Fijate que los flags van separado unicamente por espacios $crear .="num2 TINYINT (3) UNSIGNED ZEROFILL, "; # en num3 identico al anterior aadiremos un valor por defecto # de manera que cuando se aadan registros a la tabla # se escriba automaticamente ese valor 13 en el caso # de que no le asignemos ninguno a ese campo # por ser numrico 13 no va entre comillas $crear .="num3 TINYINT (7) UNSIGNED ZEROFILL DEFAULT 13, "; # ahora un nmero decimal num4 tipo REAL con 8 digitos en total # de los cuales tres sern decimales y tambin rellenaremos con ceros # Pondremos como valor por defecto 3.14 $crear .="num4 REAL (8,3) ZEROFILL DEFAULT 3.14, "; # aadamos una fecha $crear .="fecha DATE, "; /* una cadena con un limite de 32 carcter con BINARY para que diferencie Pepe de PEPE */ $crear .="cadena VARCHAR(32) BINARY, "; /* un ultimo campo opcion del tipo ENUM que solo admita
como valores SI, NO, QUIZA fijate en las comillas y en el parentesis cuidado...!! aqui no ponemos coma al final es el ltimo campo que vamos a insertar y no necesita ser separado. Si la pones dar un ERROR */ $crear .="opcion ENUM('Si','No','Quiza') "; # solo nos falta aadir el parntesis conteniendo toda la instruccin $crear .=")Type=MyISAM"; /* tenemos completa la sentencia MYSQL solo falta ejecutarla crear la conexin y ejecutarla */ /*incluimos los parmetros de conexin */ include('mysqli.inc.php'); /* incluimos dos opciones de proceso y de programacion orientada a objetos. Podemos ejecutar los ejemplos pasado mediante el metodo GET el tipo elegido. */ if(!empty ($_GET['tipo'])){ $tipo_script=$_GET['tipo']; }else{ $tipo_script="objetos"; } /*En caso de tipo proceso utilizaramos esto */ if ($tipo_script=="proceso"){ /****** Programacin mediante procesos ***********/ #conexion, seleccin de tabla y verificacion de errores segun ejemplos anteriores $conexion=@mysqli_connect ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); if(!mysqli_connect_errno()==0){ print "<br>No ha podido realizarse la conexin mediante procesos<br>"; print "Error nmero: ". mysqli_connect_errno()." equivalente a: ". mysqli_connect_error(); exit(); } # gestion de la base de datos. Los parmetros requieren el ordn aqu indicado if(mysqli_query($conexion,$crear)){ print "La tabla ha sido CREADA"; }else{ print "<br>No ha podido crearse la base de datos mediante procesos<br>"; print "Error : ". mysqli_error($conexion); exit(); } mysqli_close($conexion); } /* en caso de programacion orientada a objetos */ if ($tipo_script=="objetos"){ /****** Programacin mediante objetos ***********/ #conexion, seleccin de tabla y verificacion de errores segun ejemplos anteriores $objeto=@new mysqli ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); if(!$objeto->connect_errno==0){ print "<br>No ha podido realizarse la conexin mediante objetos<br>"; print "Error nmero: ". $objeto->connect_errno." equivalente a: ". $objeto>connect_error; exit(); } # gestion de la base de datos. Los parmetros requieren el ordn aqu indicado if($objeto->query($crear)){ print "La tabla ha sido CREADA";
}else{ print "<br>No ha podido crearse la tabla mediante objetos<br>"; print "Error : ". $objeto->error; exit(); } $objeto->close(); } ?>
Mediante procesos Mediante objetos
Ver y modificar estructuras (usando MySQLi) Visualizar la estructura de una tabla (estilo por procesos)
Ver la estructura de una tabla utilizando MySQL
La sentencia MySQL que permiten visualizar la estructura de una tabla es la siguiente: SHOW FIELDS from nombre de la tabla
tambin cabra usar una sintaxis alternativa similar a esta: $resultado=mysqli_query(sentencia,$conexion); while($linea=mysqli_fech_row($resultado)){ $matriz[]=$linea; }
con lo que estaramos creando un array bidimensional con el contenido de los resultados de cada lnea. En este caso el primer ndicedel array $matriz sera un escalar que empezara en cero y se ira autoincrementando en una unidad en cada uno de los ciclos del buclewhile. El ejemplo tiene desarrollados ambos procedimientos.
<?php # incluimos una variable con el nombre de la tabla $tabla="ejemplo1"; # incluimos los datos de la conexin y la base de datos para include("mysqli.inc.php"); # establecemos la conexin con el servidor y seleccionamos la base de datos $conexion=mysqli_connect ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sentencia="SHOW FIELDS from ".$tabla; #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=mysql_query($conexion,$sentencia); # ejecutamos los bucles que comentamos mas arriba while($linea=mysqli_fetch_row ($resultado)){ foreach($linea as $valor) { print $valor."<br>"; } } #tenemos que VOLVER a EJECUTAR LA SENTENCIA MySQL porque el puntero est # AL FINAL de la ultima lnea de los resultados print("<BR> Los nuevos resultados son <br>"); $resultado=mysql_query($conexion,$sentencia); while($linea=mysqli_fetch_row ($resultado)){ $matriz[]=$linea; } # leemos ahora el array bidimensional foreach ($matriz as $indice=>$mi_linea){ foreach ($mi_linea as $indice2=>$valor){ print "<i>Indice</i>: ".$indice." <i>Indice2</i>: ".$indice2." <i>Valor</i>: ".$valor."<br>"; } } # cerramos la conexion con el servidor mysqli_close($conexion); ?>
ejemplo566.php
El procedimiento anterior nos facilita informacin sobre la estructura de la tabla pero quiz no lo haga con toda la claridad que fuera de desear. Para mejorar las prestaciones de la anterior existe una funcin alternativa que es: $matriz =mysqli_fetch_array($resultado)
idntica en cuanto a requerimientos pero recogiendo en un array los resultados de la sentencia. Ese array tiene adems la peculiaridad de incluye cada uno de los valores en dos ndices distintos. Uno de los ndices es de tipo escalar. El otro es de tipo asociativo y sus ndices son los valores del campo de la tabla del que se han extraido los resultadosativos. En este ltimo caso incorporan como ndice el nombre del campo de la tabla del que se han extrado los resultados. $matriz =mysqli_fetch_array($resultado, MYSQL_NUM)
idntica a la anterior.La inclusin del parmetro MYSQL_NUM (sin comillas )limita sus resultado a los elementos del array de ndice escalar.
Tambin idntica a las anteriores. La inclusin del parmetro MYSQL_ASSOC (sin comillas )limita ahora los resultado a los elementos del array asociativo.
<?php # incluimos una variable con el nombre de la tabla $tabla="ejemplo1"; # incluimos los datos de la conexin y la base de datos para include("mysqli.inc.php"); # establecemos la conexin con el servidor y seleccionamos la base de datos $conexion=mysqli_connect ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sentencia="SHOW FIELDS from ".$tabla; #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=mysqli_query($conexion,$sentencia); print("<br> Los resultados con mysqli_fech_array<br><br>"); while ($linea=mysqli_fetch_array($resultado)){ # leemos el array de resultados de cada una de las lineas extraidas del resultado foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* vamos a separar los elementos escalares de los asociativos comprobando si es numrico el indice de cada array */ print "<br>Los elementos de array con indice numrico son estos<br>"; $resultado=mysqli_query($conexion,$sentencia); while ($linea=mysqli_fetch_array($resultado,MYSQL_NUM)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* visualizamos los resultados cuando el indice es NO NUMRICO */ print "<br>Los elementos de array con indice no numrico son estos<br>"; $resultado=mysqli_query($conexion,$sentencia); while ($linea=mysqli_fetch_array($resultado, MYSQL_ASSOC)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } mysqli_close($conexion); ?>
ejemplo567.php
Como habrs podido observar al ejecutar el ejemplo SHOW FIELDS nos permite conocer los propiedades de cada uno de los campos de la tabla: Field (nombre del campo), Type (incluye el tipo, el tamao y los flags), Null (especificara si el campo permite
o no permite valores nulos), Key (especificara si ese campo es o es un ndice de la tabla) y Default (que incluira los eventuales valores asignados por defecto al campo).
tambin cabra usar una sintaxis alternativa similar a esta: $resultado=$objeto_mysqli->query(sentencia); while($linea=$resultado->fech_row()){ $matriz[]=$linea; }
con lo que estaramos creando un array bidimensional con el contenido de los resultados de cada lnea. En este caso el primer ndicedel array $matriz sera un escalar que empezara en cero y se ira autoincrementando en una unidad en cada uno de los ciclos del buclewhile. El ejemplo tiene desarrollados ambos procedimientos.
<?php # incluimos una variable con el nombre de la tabla $tabla="ejemplo1"; # incluimos los datos de la conexin y la base de datos para include("mysqli.inc.php"); # creamos el objeto conexin con el servidor y seleccionamos la base de datos
$objeto_mysqli=new mysqli ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sentencia="SHOW FIELDS from ".$tabla; #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=$objeto_mysqli->query($sentencia); # ejecutamos los bucles que comentamos mas arriba while($linea=$resultado->fetch_row ()){ foreach($linea as $valor) { print $valor."<br>"; } } #tenemos que VOLVER a EJECUTAR LA SENTENCIA MySQL porque el puntero est # AL FINAL de la ultima lnea de los resultados print("<BR> Los nuevos resultados son <br>"); $resultado=$objeto_mysqli->query($sentencia); while($linea=$resultado->fetch_row ()){ $matriz[]=$linea; } # leemos ahora el array bidimensional foreach ($matriz as $indice=>$mi_linea){ foreach ($mi_linea as $indice2=>$valor){ print "<i>Indice</i>: ".$indice." <i>Indice2</i>: ".$indice2." <i>Valor</i>: ".$valor."<br>"; } } # cerramos la conexion con el servidor $objeto_mysqli->close(); ?>
ejemplo568.php
El procedimiento anterior nos facilita informacin sobre la estructura de la tabla pero quiz no lo haga con toda la claridad que fuera de desear. Para mejorar las prestaciones de la anterior existe una mtodo alternativa que es: $matriz =$resultado->fetch_array()
idntica en cuanto a requerimientos pero recogiendo en un array los resultados de la sentencia. Ese array tiene adems la peculiaridad de incluye cada uno de los valores en dos ndices distintos. Uno de los ndices es de tipo escalar. El otro es de tipo asociativo y sus ndices son los valores del campo de la tabla del que se han extraido los resultadosativos. En este ltimo caso incorporan como ndice el nombre del campo de la tabla del que se han extrado los resultados. $matriz =$resultado->fetch_array(MYSQL_NUM)
idntica a la anterior.La inclusin del parmetro MYSQL_NUM (sin comillas )limita sus resultado a los elementos del array de ndice escalar. $matriz =$matriz =$resultado->fetch_array(MYSQL_ASSOC)
Tambin idntica a las anteriores. La inclusin del parmetro MYSQL_ASSOC (sin comillas )limita ahora los resultado a los elementos del array asociativo.
<?php # incluimos una variable con el nombre de la tabla $tabla="ejemplo1"; # incluimos los datos de la conexin y la base de datos para include("mysqli.inc.php");
# creamos el nuevo objeto conexin con el servidor y seleccionamos la base de datos $objeto_mysqli=new mysqli ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sentencia="SHOW FIELDS from ".$tabla; #ejecutamos mysql_query llamando a la sentencia SHOW FIELDS $resultado=$objeto_mysqli->query($sentencia); print("<br> Los resultados con fech_array<br><br>"); while ($linea=$resultado->fetch_array()){ # leemos el array de resultados de cada una de las lineas extraidas del resultado foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* vamos a separar los elementos escalares de los asociativos comprobando si es numrico el indice de cada array */ print "<br>Los elementos de array con indice numrico son estos<br>"; $resultado=$objeto_mysqli->query($sentencia); while ($linea=$resultado->fetch_array(MYSQL_NUM)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } /* visualizamos los resultados cuando el indice es NO NUMRICO */ print "<br>Los elementos de array con indice no numrico son estos<br>"; $resultado=$objeto_mysqli->query($sentencia); while ($linea=$resultado->fetch_array( MYSQL_ASSOC)){ /* leemos el array de resultados de cada una de las lineas extraidas del resultado e insertamos un texto que nos ayude a ver lo contenidos de cada linea en la pantalla */ print "<br>Nueva lnea<br>"; foreach($linea as $indice=>$valor) { print ("El indice es: ".$indice." y el valor es: ".$valor."<br>"); } } $objeto_mysqli->close(); ?>
ejemplo569.php
Manipulacin de tablas
Borrar tablas
Las sentencias MySQL que permiten borrar una tabla son las siguientes: DROP TABLE IF EXISTS from nombre_de_la_tabla o DROP TABLE from nombre_de_la_tabla
la diferencia entre ambas radica en que usando la primera no se generara ningn error en el caso de que tratramos de borrar una tabla inexistente.
Aqu tienes el cdigo fuente de dos ejemplos que utilizan las distintas opciones de programacin.
Ver cdigo fuente mediante procesos Ver cdigo fuente mediante objetos
Es posible modificar la estructura de una tabla -en este caso borrar un campo- siguiendo un procedimiento similar a los anteriores. La nica diferencia estriba en utilizar la sentencia MySQL adecuada. Resulta obvio que el campo debe existir para que pueda ser borrado y si no existiera, es obvio tambin que se producira un error. Aqu tienes el cdigo fuente de dos script que borran uno de los campos de una tabla.
Ver cdigo fuente mediante procesos Ver cdigo fuente mediante objetos
La sintaxis es similar a la de la creacin de tablas: el nombre del campo debe ir seguido del tipo sin otra separacin que el espacio. Aqu tienes el cdigo fuente de dos script que aadem uno de los campos de una tabla.
Ver cdigo fuente mediante procesos Ver cdigo fuente mediante objetos
Transcribimos el desarrollo un ejemplo anterior de creacin de una tabla e insercin de registros utilizando diversos mtodos. La nica diferencia entre lo que tratemos aqu y lo que hemos visto aqu ser la forma de comunicacin entre PHP y MySQL. El proceso es el siguiente:
Creacin de la tabla
Empezaremos creando una tabla a la que llamaremos demo4 y que contendr los siguientes campos:
Contador, que ser de tipo TINYINT(8) (nmero entero con un mximo de 8 dgitos) que contenga solo valores positivos, que se rellene automticamente con ceros por la izquierda y que se autoincremente cada vez que aadimos un registro. DNI, destinado a recoger valores de nmeros de DNI y que debe poder contener un mximo de ocho caracteres. Lo definiremos de tipo CHAR porque sus valores, pese a ser numricos, nunca van a requerir ningn tratamiento aritmtico. Nombre, Apellido1 y Apellido2 sern tres campos tipo VHAR de tamaos mximos respectivos de 20, 15 y 15 caracteres. Su finalidad la evidencian los nombres de campo. Les asignaremos el flag NOT NULL aunque no sea totalmente correcto dado que existen pases en los que se utiliza un solo apellido. Nacimiento ser un campo tipo DATE al que asignaremos como valor por defecto el de 1970-12-21. Recuerda que MySQL trata las fechas en ese orden (ao-mes-dia) y que admite como separadores tanto - como / por lo que son vlidas entradas con cualquiera de estos formatos: 1970-12-21 1970/12/21, aunque esta segunda es convertida automaticamente al primer formato por MySQL. Hora ser un campo tipo TIME al que asignaremos como valor por defecto el de 00:00:00. Recuerda que MySQL trata las horas en ese orden (hh:mm:ss) y que slo admite como separador :. Este campo est destinado a recoger la hora de nacimiento que aunque no tiene demasiado sentido es una buena excusa para introducir este tipo de campo. Sexo ser un campo tipo ENUM que tendr dos opciones: M (masculino) y F(femenino) y al que asignaremos M como valor por defecto. Fumador ser un campo tipo CHAR(0) que por su estructura -cadena de longitud cero- tendr dos nicas opciones de valor: NULL "", que, como veremos, son valores distintos para MySQL. Idiomas ser un campo tipo SET definido para los valores: Castellano, Francs, Ingls, Alemn, Blgaro y Chino y que podr contener, como ocurre con los campos de este tipo, ninguno, uno o varios de los valores de la lista. ndice primario ser tratado como tal el campo DNI ya que se trata de un valor nico para cada persona y que, como tal, no puede tener duplicados. ndices auxiliares. Para ejemplificar su tratamiento consideraremos el campo Contador como ndice secundario. El cdigo fuente del fichero que genera esta tabla puedes verlo aqu debajo
Ver cdigo fuente
Aadir un registro
Cuando se aade un registro en una tabla los valores pueden aadirse en la propia sentencia MySQL o ser recogidos de los valores de variables PHP previamente definidas. En este ejemplo tienes el cdigo fuente del primero de los casos, en el que se aade a la tabla anterior un registro cuyos valores son:
DNI Nombre Apellido1 Apellido2 Nacimiento Sexo Hora Fumador Idiomas
16:24:52 NULL
Presta atencin a los siguientes aspectos: En la sentencia no se alude al campo Contador. La razn es que se trata un campo AUTOINCREMENTAL y en ese tipo de campos los valores de los registros se escriben automticamente cada vez que se aade uno nuevo. El registro no se aadira si el valor de DNI coincidiera con otra ya existente en la tabla. Recuerda que habamos definido ese campo como ndice primario. Si no hubiramos incluido el aviso de error no tendramos ninguna referencia sobre el xito de la insercin y no detectaramos el problema de duplicidad. Sencillamente ocurrira que el registro no se aadira pero no nos enteraramos de tal circunstancia. Si en los valores de nombre y apellidos hubiramos insertado textos ms largos del tamao establecido para ellos al crear la tabla, las cadenas se recortaran y slo se aadiran -de izquierda a derecha- los n primeros caracteres de la cadena.
Si en la fecha de nacimiento hubiramos introducido una cadena vaca nos habra puesto el valor por defecto, pero si hubiramos introducido un valor no vlido nos habra escrito 0000-00-00. Seran valores no vlidos en este caso: Los que tuvieran como valor de mes alguno no perteneciente al intervalo [1,12]. Los que tuvieran como valor de da un valor no vlido en concordancia con el mes y el ao. Admitira 29 en un mes defebrero slo en el caso de que el ao fuera bisiesto. Cuando la secuencia no coincidiera con esta AAAA-MM-DD. Cuando los separadores no fueran (-) o (/). En el campo Sexo si hubiramos introducido una cadena vaca nos habra puesto M (valor por defecto) pero si hubiramos intentado introducir un valor que no fuera M ni F nos habra insertado una cadena vaca. El campo hora se comportara de idntica forma al de fecha salvo que aqu la secuencia es: hh:mm:ss, que la hora debe pertenecer al intervalo [0,23], los minutos y los segundos a [0,59] y que el nico separador vlido en este caso es (:). El campo Fumador requiere particular atencin ya que se trata de un campo CHAR(0) que slo admite dos valores: NULL ocadena vaca, que como recordars son distintos para MySQL. Para introducir el valor NULL utilizando el procedimiento de insercin de este ejemplo tienes que escribir NULL, sin ponerlo entre comillas, tal como lo he hecho en el ejemplo . Para introducir una cadena vaca en este campo bastara con que pusieramos '' (ojo no es una comilla doble es la comilla sencilla (') repetida dos veces! Date cuenta de que si pusiramos comillas dobles tendramos un error ya que hay unas comillas dobles delante delINSERT que se cierran al final de la sentencia MySQL y que no podemos volver a escribirlas entre ambas para evitar unfalso cierre de la cadena que contienen. En este caso el valor del campo Idiomas puede contener valores decimales comprendidos entre 0 y 64 o entre sus equivalentes binarios que son 0 y 111111. El valor 64 lo justifica el hecho de que son seis los elementos que puede contener el campo (hemos definido: Castellano, Francs, Ingls, Alemn, Blgaro y Chino que son seis y que el caso de insertarlos todos requerira el nmero binario 111111, cuyo valor decimal es precisamente 64. El valor 3 significa lo mismo que su equivalente binario (11) o mejor (000011) lo cual quiere decir que, como el primer carcter de la derecha es uno el campo toma el primer elemento de la lista (Castellano), como el segundo (de derecha a izquierda) tambin esuno tomar tambin el segundo elemento de la lista (Francs) y por ser cero todos los dems no tomar ningn otro valor de la lista, con lo que la cadena resultante sera en este caso Castellano, Francs. Fjate tambin en que el valor 3 no lo hemos puesto entre comillas porque se trata de una expresin decimal. Qu ocurra si hubiera puesto 11? Lo habra interpretado como once (decimal) o como tres (binario)?. La solucin es simple: '11' (entre comillas) sera interpretado como binario, sin comillas como decimal. No es necesario introducir valores en todos los campos, es decir, que la lista de campos de la sentencia INSERT puede no contenerlos a todos. No es necesario escribir el nombre de los campos en el mismo orden en el que fueron creados pero si es imprescindible quecampos y valores estn escritos en la sentencia INSERT exactamente en el mismo orden y tambin que en esa sentencia elnmero de campos y el nmero de valores sea el mismo. Recuerda que los values tipo numricono se incluyen entre comillas, mientras que los no numricos tienen que estar contenidos entre comillas incluso en el caso de no se inserten directamente sino a travs de una variable PHP.
Observa en el cdigo fuente que al insertar las variables en los VALUES de la sentencia MySQL ponemos cuando se trata de valores tipo cadena '$variable' (el nombre de la variable entre comillas) y cuando se trata de valores nmericos sin comillas. Si quieres introducir el valor NULL en un campo tipo VAR(0) define la variable as: $variable="NULL" y si quieres introducir unacadena vaca defnela de este otro modo:$var="''" -comillas dobles (") seguidas de dos comillas sencillas (') y para terminar otras comillas dobles (") y cuando hagas alusin a esa esta variable como un VALUE en la sentencia de insercin no la pongas entre comillas.
permite algunos modificadores opciones tales como: INSERT [LOW_PRIORITY | DELAYED] [IGNORE] tabla (campo1,campo2,..) VALUES (valor1,valor2,..)
de ellos LOW_PRIORITY y DELAYED son incompatibles por lo que solo cabe uno u otro pero no ambos. Veamos su utilidad. La insercin de registros y la lectura de una tabla son procesos incompatibles, pero cabe la posibilidad de que se intenten ejecutar simultneamente. No olvides que estamos en Internet y es perfectamente posible que desde dos ordenadores distintos, dos personas distintas estn accediendo a la misma tabla simultneamente y que uno de los accesos sea de escritura, es decir: aadir,modificar o borrar campos en la tabla. Quin tiene preferencia de paso? Quien tiene que esperar?. Si la opcin LOW_PRIORITY est activada, el proceso de escritura esperar a que terminen los procesos de lectura activos, pero si est activa la opcin DELAYED el proceso de lectura se interrumpir automticamente para ceder el paso al de escritura. Respecto a la opcin IGNORE tiene utilidad cuando se trata de realizar una secuencia de inserciones. Si no est activa en el momento en el que aparezca una clave duplicada se interrumpir el proceso de insercin, por el contrario, si estuviera activa el proceso de insercin continuar con los siguientes registros de la secuencia, aunque -como es lgico- seguirn sin insertarse los registros con clave duplicada.
que devuelve el nmero de registros afectados por la ejecucin de la ltima instruccin mysqli_query que utiliz el identificador de conexin $conexion. En el caso de que la programacin de nuestros scripts est orientada a objetos disponemos de la propiedad: $objeto->affected_rows
cuyo valor es nmero de registros afectados por la ltima ejecucin del mtodo $objeto->query(). En los ejemplos siguientes hay ejemplos de utilizacin de este cuantificador.
mediante procesos
mediante objetos
Como ves, variable es el nombre de la variable (esta vez sin $ delante, recuerda que no estamos en PHP sino en HTML) y va seguidode [ ] precisamente para indicar que es un array. Lo que respecta a SIZE=6 no es otra cosa que el parmetro que indica cuntos elementos de la lista de opciones queremos que se visualicen simultneamente en la pgina. El elemento ms importante son los values de cada option dentro de ese select. Los hemos escrito as: <option value=1>Castellano <option value=2>Francs <option value=4>Ingls <option value=8>Alemn <option value=16>Blgaro <option value=32>Chino
Fjate que hemos mantenido exactamente el mismo orden en el que han sido definidos en el campo SET de la tabla. Observa tambin los valores: 1, 2, 4, 8, 16 y 32 que son precisamente las potencias de 2: 2 ,2 ,2 ,2 ,2 ,2 ,y2
0 1 2 3 4 5 6
Al ir seleccionando valores, van aadindose al array. Por ejemplo. Si seleccionamos Francs y Blgaro el array sera este: var[0]=2,var[1]=16 Si sumamos esos valores (2 + 16) el resultado sera 18, y al convertir a binario este valor, resultar: 010010 que es como decirle a MySQL (mirando la cadena de derecha a izquierda, lo recuerdas?) que incluya los valores segundo (Francs) y quinto (Blgaro) del SELECT MULTIPLE que corresponden a las posiciones en las que la cadena binaria contiene un uno.
Los valores de esos tres campos (tanto en fecha como en hora) los recogemos en variables que son elementos de dos array escalares. El campo sexo la recogemos en input tipo radio y les asignamos valores M F que coinciden con los valores del campo ENUM de la tabla. Con el campo Fumador -opcin Fumador/No fumador - hacemos exactamente lo mismo, pero asignndoles valores 1 o 0 ya que el formulario no permite la opcin NULL cadena vacia. En el script posterior ser cuando modifiquemos los valores de esas variables. Para el campo Idiomas utilizamos una opcin select de tipo mltiple y para los values un pequeo truco que describimos aqu la izquierda. Pues bien, aqu tienes, cdigo fuente del formulario que hemos diseado
Ver cdigo fuente
En realidad, tal como habrs podido ver en el cdigo fuente, la depuracin ha sido la siguiente: Hemos creado un valor de fecha y hora en formatos MySQL vlidos de la forma que describimos un poco ms arriba. Hemos sumado todos los valores numricos recibidos en el array obtenido del SELECT MULTIPLE y hemos asignado el resultado a la variable depurada que recoge el valor a escribir en el campo Idiomas. La justificacin de esa suma la tienes al margen. La variable Fumador es la que tiene un poquito ms de complicacin. Vemosla con calma: Los valores que recibimos desde formulario son 1 o 0 y hemos de transformarlos en una cadena vaca o en NULL. Hemos insertado un operador condicional (un if... else) para convertir eso valores en: $var="'\N'" (comilla doble, comilla simple, barra invertida, N, comilla simple y comilla doble) $var="''" (comillas dobles, dos comillas simples y unas comillas dobles) Asignados los nuevos valores tenemos que recurrir a un pequeo truco. Venimos repitiendo que en la sentencia INSERT losnombres de las variables no numricas que contienen los values hay que escribirlos dentro de comillas simples, pero en el caso de un campo tipo CHAR(0) hemos de hacer una excepcin que sera no poner esas comillas al nombre de la variable. Al hacerlo as, se escribiran como valores en la sentencia de insercin uno de estos: ='\N' o =' ' (los valores de la variable) que al contenercomillas ya son interpretados por MySQL como una cadena.
SQL_BIG_RESULT Es una clusula opcional que se usa para indicar al optimizador que el resultado va a tener una gran cantidad de registros. En ese caso, MySQL utilizar tablas temporales cuando sea necesario para optimizar la velocidad de gestin de la informacin. Esta clusula tambin puede ser utilizada dentro de GROUP BY. SQL_BUFFER_RESULT Es opcional y su finalidad es la de forzar a MySQL a tratar el resultado en un fichero temporal. Ese tratamiento ayuda a MySQL a liberar recursos ms rpidamente y es de gran utilidad (siempre desde el punto de vista de la rapidez) cuando es necesario un largo proceso de clculo antes de enviar los resultados al cliente. HIGH_PRIORITY Esta clusula, opcional da prioridad al comando SELECT sobre otros comandos que simultneamente pudieran estar intentando acceder a la tabla para escribir en ella (aadir o modificar registros). Si esta opcin est activa, los intentos de escritura que pudieran producirse de forma simultnea deberan esperar al final de este proceso para ejecutarse. campo1, campo2, ... Tienen carcter obligatorio y sealan los campos de la tabla que deben incluirse en la consulta. La consulta slo devolver informacin de aquellos campos que estn enumerados aqu. Si se desea incluir a todos campos bastar con excribir * en esta posicin. En este caso *tiene la condicin de carcter comodn cuyo significado es todos los campos. Los campos numricos pueden llevar asociadas funciones MySQL que devuelven informacin estadstica. La sintaxis de algunas de esas funciones es la siguientes: MAX(campo) Devuelve el mayor de los valores de ese campo de entre todos los registros de la la consulta. Los registros comparados puedes ser todos o una parte de ellos. Si la sentencia incluye la condicin GROUP BY, en cuyo caso devolver el mximo de cada grupo y si incluye la opcin WHERE solo sern comparados los registros que cumplan tal condicin. MIN(campo) Idntica a la anterior en cuanto a criterios de seleccin, esta funcin devuelve el manorde los valores del campo en el mbito establecido por las evuntuales condiciones que pueda incluir la sentencia. AVG(campo) Devuelve el valor promedio de todos los registros numricos seleccionados con los mismos criterios del caso anterior. SUM(campo) Devuelve la suma de todos los valores del campo seleccionado y en el mbito establecido por los parmetros de la consulta. STDDEV(campo) Devuelve la estimacin de la desviacin tpica de la poblacin formada por los valores del campo. COUNT(campo) Cuenta los valores no nulos del campo indicado. Cuando se aplica una de estas funciones el resultado de la consulta contiene una sola lnea, salvo que se incluya opcinGROUP BY, en cuyo caso devolver tantas lneas como grupos resulten. FROM tabla Esta expresin indica a MySQL el nombre de la tabla en la que debe efectuarse la consulta. WHERE definicion Esta instruccin tiene carcter opcional y su utilidad es la de filtrar la consulta estableciendo los criterios de seleccin de losregistros que debe devolver. Si se omite WHERE, la consulta devolver todos los registros de la tabla. En la tabla de ejemplos tienes informacin sobre las formas de definir los criterios de seleccin de esta opcin. GROUP BY definicion Tiene carcter opcional y su finalidad es la de presentar los resultados de la consulta agrupados segn el criterio establecido en su definicin. Resulta de gran utilidad cuando se pretende obtener valores estadsticos de los registros quecumplen determinadas condiciones (las condiciones del agrupamiento). ORDER BY definicion Tambin tiene carcter opcional y su utilidad es la de presentar la informacin de la consulta ordenada por los contenidos de uno o varios campos. Siempre tiene como opcin complementaria de que en cada campo utilizado para la ordenacinpuede establecerse uno de estos criterios ASC (ascendente, es el valor por defecto) o DESC (descendente). Si no se establece ningn orden los resultados de la consulta aparecern en el mismo orden en el que fueron aadidos los registros. LIMIT m, n Esta clusula es opcional y permite establecer cuntos y cules registros han de presentarse en la salida de la consulta. Por ejemplo: LIMIT 4, 8 indicara a MySQL que la consulta debera mostrar OCHO registros contados a partir del quinto (s, el quinto porque LIMIT considera el primer registro como CERO). El criterio lmite se aplica sobre los resultados de la salida, es decir, sobre los resultados seleccionados, ordenados yfiltrados siguiendo los criterios establecidos por las clusulas anteriores. Si se escribe
como un solo parmetro (LIMIT k), MySQL lo interpretar como que k es el segundo de ellos y que el primero es CERO, es decir: LIMIT 0, k
La consulta ms simple
Si utilizamos la sentencia SELECT * FROM tabla
obtendremos informacin sobre todos los campos (*) y la salida estar en el mismo orden en el que fueron aadidos los datos. Si visualizas este ejemplo, vers que aparecen ordenados por el valor autonumrico del campo Contador lo cual, como ves, resulta coherente con la afirmacin anterior.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
y tendremos como resultado una lista completa, por el mismo orden que la anterior, pero slo mostrando los campos indicados.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
y tendremos como resultado una lista que contendr m registros a partir del n+1, por el mismo orden que la anterior, y mostrando los campos indicados.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
y tendremos como resultado una lista ordenada por el primero de los campos indicados en ORDER BY, y en caso de coincidencia de valores en ese campo, utilizaramos el criterio de ordenacin sealado en segundo lugar.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
que nos devolver la lista de registros que cumplen la condicin indicada. Aqu tienes un ejemplo muy sencillo.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
dnde $array es un array escalar que contiene los valores del registro actual (aquel que seala el puntero interno). Los ndices de este array van asociados al orden en el que estn escritos los nombres de los campos dentro de la sentencia select. Si no se indica otra cosa el puntero comienza un recorrido por el primer registro del resultado (fila 0) y en las sucedsivas llamadas a mtodo fetch_row se va desplazando a la siguiente fila. Por eso, mediante un bucle while podemos recorriendo los diferentes registros del resultado y convirtiendo cada uno de ellos en un array escalar. Aqu tienes un ejemplo
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
Los valores contenidos en cada fila de los resultados tambin pueden leerse mediante
$array=mysqli_fetch_assoc($resultado) o $array=$resultado->fetch_assoc()
dnde $array es un array asociativo que contiene los valores del registro actual (aquel que seala el puntero interno). Los ndices de este array son los nombres de los campos dentro de la sentencia select. Si no se indica otra cosa el puntero comienza un recorrido por el primer registro del resultado (fila 0) y en las sucedsivas llamadas a mtodo fetch_assoc se va desplazando a la siguiente fila. Por eso, mediante un bucle while podemos recorriendo los diferentes registros del resultado y convirtiendo cada uno de ellos en un array asociativo. Aqu tienes un ejemplo
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
Una tercera opcin para ir leyendo los valores contenidos en cada fila de los resultados es la que utiliza $objeto=mysqli_fetch_object($resultado) o $objeto=$resultado->fetch_object()
dnde $objeto es un objeto cuyas propiedades son los nombres de los campos incluidos en la sentencia select y el valor el resultante de la consulta para ese campo en la fila actual (aquella a la que apunta el puntero interno). Si no se indica otra cosa el puntero comienza un recorrido por el primer registro del resultado (fila 0) y en las sucesivas llamadas a mtodo fetch_object se va desplazando a la siguiente fila. Por eso, mediante un bucle while podemos recorriendo los diferentes registros del resultado y convirtiendo cada uno de ellos en un objeto con las propiedades descritas. Aqu tienes un ejemplo
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
En esta nueva opcin se realiza un lectura nica del contenido de todas las filas $array_bidimensional=mysqli_fetch_all($resultado) o $array_bidimensional=$resultado->fetch_all()
dnde $array_bidimensional es un array cuyo primer ndice coincide con el nmero de orden (empezando por cero) de cada una de las filas del resultado y cuyo segundo ndice es el nmero de columna entendiendo como tales cada uno de los campos incluidos en la sentencia SELECT por el orden de inclusin enla misma y contados a partir de cero. La extraccin de los diferentes valores requerira un doble bucle de lectura. El primero nos ira posicionando en cada una de las filas del resultado (el primer ndice) y el segundo bucle recorrera todos de aquella fila. Aqu tienes un ejemplo
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
Hay situaciones en las que puede resultarnos de inters conocer nicamente los valores de alguno o algunos de los registros incluidos en el resultado de una consulta. Puede, por ejemplo, que nos interese conocer el nicamente el primer registro (o el ltimo, o el que ocupa la posicin 38) tal como aparecen en el resultado de la ejecucin de la funcin mysqli_query o del mtodo query() si se trata de objetos. Tanto la funcin mysql_fech_row() como el mtodo fetch_row() extreaen aquel registro (fila de datos) al que seala el apuntador. Para posicionar de forma arbitrarie el apuntador de resgistros mysqli dispone las siguientes funciones:
mysqli_data_seek($resultado, posicion)
dnde $resultado es el objeto resultante de una consulta realizada por medio de la funcin mysqli_query() y posicin es un nmero entero que explicita la posicin (la prima posicin se identifica mediante cero) a la que pretendemos orientar el apuntador de lectura demysqli_fetch_row. El proceso podra ser similar a este: $resultado=mysqli_query($identificador,sentencia_MySQL); // realiza la consulta y recoge el resultado en la variable $resultado mysqli_data_seek($resultado,posicion); //Sita el apuntador en la fila sealada por posicin $fila=mysqli_fetch_row($resultado); //Lee el registro (fila) que seala en apuntador anterior y recogiendo el resultado en el array $fila
Cuando se trata de que la programacin est orientada a objetos el mtodo que debemos utilizar es el siguiente: $resultado->data_seek(posicion)
dnde $resultado es el objeto resultante de una consulta realizada por medio del mtodo $objeto->query() y posicin es un nmero entero que explicita la posicin (la prima posicin se identifica mediante cero) a la que pretendemos orientar el apuntador de lectura que usar el posterior mtoco fetch_row. El proceso podra ser similar a este: $resultado=$objeto->query(sentencia_MySQL); // el mtodo query realiza la consulta y recoge el resultado en el nuevo objeto $resultado $resultado->data_seek(posicion); //Sita el apuntador en la fila sealada por posicin $fila=$resultado->fetch_row(); //Lee el registro (fila) que seala en apuntador anterior y recogiendo el resultado en el array $fila
Como es lgico tambin pueden usuarse fetch_object fetch_assoc en lugar del fetch_row del pseudocdigo anterior.
Consultas condicionadas
La clasula WHERE permite un variado abanico de condiciones, que trataremos de resumir aqu. Algunos de ellas son los siguientes:
Programacin Progamacin por orientada a procesos objetos Cdigo Ver Cdigo fuente ejemplo fuente Selecciona los registros que contienen en el campo un valor igual a num Selecciona los registros que contienen en el campo una cadena idntica a cadena(*) Selecciona los registros que contienen en el campo un valor menor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres son menores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**) Selecciona los registros que contienen en el campo un valor menor O igual a num Ver Ver Ver Probar Probar Probar Ver Ver Ver Ver ejemplo Probar Probar Probar
Operador
Descripcin
Numrico WHEREcampo<num
Cadena
WHEREcampo<"cadena"
Ver
Probar
Ver
Probar
Numrico WHEREcampo<=num
Ver
Probar
Ver
Probar
<=
Cadena
WHEREcampo<="cadena"
Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres son menores que los de la cadena, siendo n el nmero de caracteres que Ver contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo un valor mayor a num Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres son mayores que los de la cadena, siendo n el nmero de caracteres que contiene cadena. (**) Ver
Probar
Ver
Probar
> >
Numrico WHEREcampo>num
Probar
Ver
Probar
Cadena
WHEREcampo>"cadena"
Ver
Probar
Ver
Probar
>=
Numrico WHEREcampo>=num
Selecciona los registros que contienen en el campo un valor mayor o igual a num
Ver
Probar
Ver
Probar
>=
Cadena
WHEREcampo>="cadena"
Selecciona los registros que contienen en el campo una cadena cuyos n primeros caracteres son mayores que los de la cadena, siendo n el nmero de caracteres que Ver contiene cadena y aade respecto al caso anterior la opcin de que en caso de que ambos valores fueran iguales tambin los presentara (**) Selecciona los registros que contienen en el campo valores que coinciden con alguno de los especificados dentro del parntesis. Cuando se trata de valores no numricoz han de ir entre comillas Ver
Probar
Ver
Probar
IN
Probar
Ver
Probar
Numrico
BETWEEN o
Cadena
Selecciona los registros en los que los valores contenidos en el camposeleccionado estn comprendidos en el intervalo valor1 (mnimo) valor2(mximo) incluyendo en la seleccin ambos extremos. Ver Cuando los contenidos de los campos son cadenas sigue los mismos criterios que se indican para los dems operadores de comparacin Selecciona los registros en los que los valores contenidos en el camposeleccionado son NULOS Selecciona los registros en los que los valores contenidos en el camposeleccionado son NO NULOS Ver Ver
Probar
Ver
Probar
Cadena Cadena
Probar Probar
Ver Ver
Probar Probar
(*) Cuando se trata de cadenas de caracteres, el concepto menor que significa anterior en la ordenacin de los caracteres segn su cdigo ASCII y mayor quesignifica posterior en esa misma ordenacin. (**) La discriminacin de Maysculas/Minsculas depender del tipo de campo. Recuerda que los tipo BLOB hacen esa discriminacin, mientras que los de tipo TEXT son insensibles a Maysculas/Minsculas.
Cuando se trata de comparar cadenas MySQL dispone de una potente instruccin (LIKE) que permite establecer los criterios de seleccin a toda o parte de la cadena. Su sintaxis contempla distintas posibilidades utilizando dos comodines>: % (que se comporta de forma similar al (*) en las bsquedas de Windows) y _ (de comportamiento similar a (?) en Windows). Aqu tienes algunas de sus posibilidades:
Progamacin por procesos Cdigo fuente Ver Ver Ver Ver Ver ejemplo Probar Probar Probar Probar Programacin orientada a objetos Cdigo fuente Ver Ver Ver Ver Ver ejemplo Probar Probar Probar Probar
Sintaxis
Descripcin
WHERE campoLIKE '%cadena%' WHERE campoLIKE 'cadena%' WHERE campoLIKE '%cadena' WHERE campoLIKE '_cadena%'
Selecciona todos los registros que contengan la cadena en el campo indicado sea cual fuere su posicin Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente alprincipio del campo Selecciona todos los registros en los que el campo indicado que contengan la cadena exactamente al final del campo Selecciona todos los registros en los que el primer caracter del campo puede ser cualquiera pero los siguientes han de ser exactamente los indicados en cadena pudiendo ir seguidos de cualesquiera otros caracteres
El comodn (_) puede ir tanto al principio como al final y puede repetirse tantas veces como sea necesario. Por tanto sera correctoLIKE '___es%' y tambin LIKE 'a___es%' as como: LIKE '%a___es'. La clasula WHERE aun tiene ms opciones. Acepta mltiples condiciones vinculadas por los operadores lgicos AND, OR, NOT o sus sintaxis equivalentes: &&, || y !. El comportamiento de estos operadores es idntico al descrito para sus homnimos de PHP en esta pgina
obtendramos UNA SOLA FILA cuyos valores seran los resultados de la aplicacin de las funciones a todos los registros del campo indicado. Aqu tienes un ejemplo que determina todos los valores de esos estadsticos aplicados al campo Contador de nuestra tabla demo4.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
<
Las diferentes opciones de formato las tienes en la tabla. Es importante tener en cuenta que la sintaxis correcta es %Y (sin espacio) ya que si hubiera un espacio % Y interpretara la letra Y como un texto a incluir. CURDATE()
Dentro de DATE_FORMAT se puede incluir -en vez del nombre del campo- una cadena en la que se indique una fecha en formatoYYYY-MM-DD hh:mm:ss. Puedes verlo en los ejemplos. De igual modo es posible sustituir el nombre del campo -o la cadena- por la funcinCURDATE() que recoge la fecha actual del sistema (nicamente da, mes y ao). A efectos de horas, minutos y segundos CURDATE() va a tomar el medioda de la fecha actual. CURTIME()
Se comporta de forma similar a CURDATE(). Devuelve la hora actual del sistema que alberga el servidor MySQL en formato hh:mm:ss CURRENT_TIMESTAMP()
Se comporta de forma similar a CURDATE(). Devuelve la fecha y hora actual del sistema en formato YYYY-MM-DD hh:mm:ss NOW()
Es un alias de CURRENT_TIMESTAMP().
Formato
Descripcin
Sentencia MySQL
Progamacin por procesos Cdigo fuente Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver ejemplo Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar
Programacin orientada a objetos Cdigo fuente Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver Ver ejemplo Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar Probar
%d %e %D %m %c %M %b %y %Y %w %W %W %j %U %u
Da del mes en formato de dos dgitos Da del mes en formato de uno dos dgitos Nmero de da seguido del sufijo en ingls Nmero del mes en formato de dos dgitos Nmero del mes en formato de uno o dos dgitos Nombre del mes (en ingls) Nombre del mes abreviado (en ingls) Nmero del ao en formato de dos dgitos
Nmero del ao en formato de cuatro dgitos DATE_FORMAT(Nacimiento,'%Y') Nmero de da de la semana 0=Domingo ... 6=Sbado Nombre del da de la semana (en ingls) Nombre abreviado del da de la semana (en ingls) Nmero de da del ao en formato de 3 dgitos Nmero de semana del ao considerando el DOMINGO como primer da de la semana (dos dgitos) Nmero de semana del ao considerando el LUNES como primer da de la semana (dos dgitos)
Ver
Probar
Ver
Probar
La fecha para los ejemplos siguientes la extraemos de una variable del tipo: $fecha="2005-10-12 14:23:42" ya que la tabla no contiene campos de fecha que incluyan horas, minutos y segundos %H %k %h %I %i %s %r %T % texto %p
Hora con dos dgitos (formato 0 a 24 horas) Hora con uno dos dgitos (formato 0 a 24 horas) Hora con dos dgitos (formato 0 a 12 horas) Hora con uno dos dgitos (formato 0 a 12 horas) Minutos con dos dgitos Segundos con dos dgitos
Hora completa (HH:mm:ss) en formato de 12 DATE_FORMAT($fecha,'%r') horas indicando AM PM Hora completa (HH:mm:ss) en formato de 24 DATE_FORMAT($fecha,'%T') horas Incluye el texto que se indica detrs del % Aade AM PM dependiendo de la Hora
Se pueden combinar a voluntad varias opciones utilizando una sintaxis de este tipo: '% Hoy es: %d - %m - %Y % es %W % estamos en el mes de %M % <br>y van transcurridos %j % dias de este ao.<br>Son las %r'
Setencias mltiples
Cuando usamos mysqli podemos ejecutar mltiples sentencias en una sola instruccin. Para ello debemos empezar encadenando las sucesivas sentencias incluyndolas una a continuacin de otra y separndolas mediante un punto y coma (;). SELECT * FROM tabla1 ; SELECT campo1 FROM tabla2 ; DROP TABLE IF EXISTS tabla3
dnde, en el caso de programacin mediante procesos, $conexion es el identificador de la conexin y sentencia_multiple el una sentencia mltiple en el formato comentado en el prrafo anterior. Devuelve un valor booleano (true o false). Cuando se trata de programacin orientada a objetos es preciso recurrir al mtodo multi_query que mediante la sintaxis: $objeto->multi_query(sentencia_multiple) en la que sentencia_multiple es una sentencia mltiple en el formato comentado anteriormente. Devuelve un valor booleano (true o false).
Cuidado! Los mensajes de error slo se visualizan en le caso de producirse este en la ejecucin de la primera de las sentencias
Pese a incluir un condicional para advertirnos de eventuales errores solo se activara el mensaje de error en el caso de que este se produjese en la primera de las sentencias.
Transfiere a $resultado el conjunto de resultados de la ltima consulta en la conexin de base de datos. En el primer caso (usando procesos) se requiere el parmetro $conexion. En el segundo supuesto (orientado a objetos) el mtodo no requiere ningn parmetro. $resultado=mysqli_use_result($conexion) o $resultado=$objeto->use_result()
Se utiliza para iniciar la recuperacin de un conjunto de resultados de la ltima consulta ejecutada. Aunque a primera vista pueda parecer muy similar a lo anterior hay una importantsima diferencia dado que no se transfiere el conjunto completo de resultados y por lo tanto no se pueden utilizar funciones como mysqli_data_seek () para pasar a un registro en particular dentro del conjunto. Cuando cualquiera de las opciones (store o use) se ejecuta inmediatamente despus de la ejecucin de un multi_query recoger los resultado de la primera de las sentencias que contiene. mysqli_free_result($resultado) o $resultado->free()
Liberan la memoria ocupada por los resultados. Como en casos anteriores la primera sentencia se utiliza cuando se programa por procesos y la segunda cuando se hace por objetos. No es estrictamente necesario utilizarlos dado que toda la memoria utilizada por los resultados asociados se libera automticamente al finalizar la ejecucin del script. Slo tiene utilidad prctica en aquellos casos en los que las consultas devuelven una cantidad de datos muy grande. mysqli_more_results($conexion) o $objeto->more_results() Comprueba si hay algn resultado ms de una consulta mltiple. Devuelve un valor booleano mysqli_next_result($conexion) o $objeto->next_result() Prepara siguiente conjunto de resultados de una llamada previa a mysqli_multi_query (), que pueden ser recuperados por mysqli_store_result () o mysqli_use_result ().
Consulta mediante procesos Consulta mediante procesos Ver cdigo fuente Ver cdigo fuente Consulta mediante objetos Consulta mediante objetos Ver cdigo fuente Ver cdigo fuente
en la que, como ves, modificamos ligeramente la sintaxis ya que anteponemos el nombre de la tabla al del campo correspondiente separando ambos nombres por un punto, con lo cual no hay posibilidad de error de identificacin del campo incluso cuando campos de distinta tabla tengan el mismo nombre. Otra innovacin -respecto a los ejemplos anteriores- es que detrs de la clusula FROM escribimos los nombres de todas las tablas que est usando SELECT. A partir de ah se pueden establecer todo tipo de relaciones para las sentencias WHERE, ORDER BY y GROUP BY utilizando para ellocampos de cualquiera de las tablas sin otra particularidad ms que poner cuidado al aludir a los campos utilizando siempre la sintaxisnombre_tabla.nombre_campo. A modo de ejemplo hemos procurado comentarlo lnea a lnea aqu tienes un script PHP que hace una consulta conjunta de las tablasdemo4, demodat1, demodat2 y demodat3 y nos presenta una tabla con los datos personales y las puntuaciones de las tres pruebas as como las suma de puntos de las tres y, adems, ordena los resultados -de mayor a menor- segn la suma de las tres puntuaciones.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
El mtodo prepare prepara la SENTENCIA para su ejecucin devolviendo el resultado como un objeto $actuacion. Este mtodo no ejecuta la sentencia, solo la prepara. mysqli_stmt_execute($actuacion) o $actuacion-> execute()
El mtodo execute es propio de los objetos resultantes $actuacion de la preparacin una sentencia. Devuelve el objeto resultado de la ejecucin de esa sentencia. Este objeto permite extraer los resultados mediante: $resultado=mysqli_stmt_get_result($actuacion) o $resultado=$actuacion->get_result()
El mtodo get_result() cuando se trata de objetos o su equivalente mysqli_stmt_get_result producen un bloque de informacin idntico al que se podra obtener mediante el mtodo query o su equivalente mysqli_query. Por tanto es susceptible de ser leido mediante cualquiera de los procedimientos comentados en el epgrafe Los resultados de la sentencia SELECT de la pgina anterior. Aqu tienes un ejemplo en ambas versiones.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
Existe una opcin alternativa de lectura del objeto resultante de la ejecucin del mtodo execute. Se trata de utilizar una de las siguientes funciones: mysqli_stmt_bind_result($actuacion, $var1, $var2, $var3, ...) o $actuacion->bind_result($var1, $var2, $var3, ...)
dnde $actuacion es el nombre del objeto resultante del mtodo execute (o de mysqli_execute) $var1, $var2, $var3,.. son nombres vlidos cualesquiera de variables PHP a travs de las que se vincularn los campos de la consulta. Han de crearse obligatoriamente tantas variables como campos intervengan en la consulta. Las funciones anteriores organizan los resultados de la consulta por registros (filas) que pueden ser leidas secuencialmente de una en una y a travs de llamadas reiterativas por medio de una de estas funciones: mysqli_stmt_fetch($actuacion) o $actuacion->fetch() que irn asignando a las variables $var1, $var2, $var3,.. los valores de los campos correspondientes al registro contenido en la fila actual. La lectura comienza por el primer registro resultante de la consulta y contina secuencialmente (la lectura completa requiere la realizacin de un bucle tal como puedes ver en los ejemplos) en las sucesivas llamadas a estas funciones. Como es obvio, en cada iteracin se modificarn los valores de las variables $var1, $var2, $var3,... Las pginas oficiales de PHP justifican la utilizacin de este procedimiento cuando se trate de ahorrar recursos de memoria (el resultado de la consulta no es almacenado en ningn buffer) y, a la vez, admiten una mayor lentitud en el procesamiento de la informacin
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
puede hacrsele una modificacin incluyendo entre ambas un nuevo mtodo (bind_param) que tiene como finalidad enlazar el valor de una variable con un identificador incluido en la sentencia SQL. Una sintaxis como esta: $actuacion=mysqli_prepare($conexion,'SELECT * FROM tabla WHERE (Nombre=? and Apellido1=? and edad=?)') mysqli_stmt_bind_param($actuacion,'ssi', $var1, $var2, $var3); $var1='Jose'; $var2='Alonso'; $var3=25; mysqli_stmt_execute($actuacion) o $actuacion= $objeto->prepare('SELECT * FROM tabla WHERE (Nombre=? and Apellido1=? and edad=?)') $actuacion-> bind_param('ssi', $var1, $var2, $var3); $var1='Jose'; $var2='Alonso'; $var3=25; $actuacion-> execute()
en la que hacemos las siguientes modificaciones: En la sentencia SQL sustituimos por ? lo que anteriormente eran cadenas o nombres de variables (entre comillas por su condicin de cadenas alfanumricas) del tipo '$nombre' y '$apellido' y nmeros o variables del tipo $edad (sin comillas por su condicin de valor numrico). Agregamos una llamada al mtodo bind_param con los siguientes parmetros obligatorios:
El primero de ellos es una cadena formada por identificadores de tipo de los valores que habrn de reemplazar a los signos de interrogacin. Los identificadores de tipo (la cadena debe incluir tantos como signos de interrogacin contenga la sentencia MySQL) son los siguientes: i La variable es de tipo entero d La variable es numrica double s La variable es de tipo cadena b La variable es de tipo blob Los sealados como $var1, $var2, $var3, etctera son los nombres de las variables que habrn de estar definidas antes de invocar el mtodo execute y que contienen los valores que ha de sustituir a los sucesivos ? de la sentencia. Hemos de tener en cuenta que han de incluirse siempre tantos nombres de variable como interrogantes existan en la sentencia. El mtodo execute producira los resultados de la ejecucin de la sentencia despus de haber reemplazado los ? por los valores de la variable. Veamos un primer ejemplo en el que las variables son de tipo numrico
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
En este otro ejemplo ya hemos incluido variables tanto numricas como cadena y dnde conjugamos el uso de bind_param con el de bind_result.
Consulta mediante procesos Ver cdigo fuente Consulta mediante objetos Ver cdigo fuente
Cuidado! Hay que tener muy presente que con esta sentencia en la que no aparece WHERE se modificarn TODOS LOS REGISTROS DE LA TABLA y por lo tanto los campos modificados tendrn el mismo valor en todos los registros.
Recuento de resultados
El recuento de los resultados de la ejecucin de una sentencia tiene dos opciones que dependen del tipo de esta. Cuando se trata de sentencias que no producen modificacin en los contenidos (caso de las consultas) el recuento de resultados utiliza las funciones y sintaxis ya conocidas de $num_resultados=mysqli_num_rows($resultado) o $num_resultados=$resultado->num_rows En ambos casos la variables $num_resultados recoger el nmero de registros (filas) obtenidos como resultado de la consulta. La primera de las opciones se utiliza cuando se gestiona la consulta mediante procesos mientras que es segundo corresponde a consultas mediante objetos.
Cuando se trata de sentencias que s producen modificacin en los contenidos (altas, modificaciones o borrado de registros) el recuento de resultados requiere de esta sintaxis: $cuenta_resultados=mysqli_affected_rows($conexion) o $cuenta_resultados=$objetoMySQLi->affected_rows En el primer caso programacin mediante procesos se utiliza la funcin mysqli_affected_rows con el parmetro identificador de conexin: $conexion En el segundo supuesto programacin orientada a objetos se utiliza la propiedad affected_rows que es la que contiene el valor de ese resultado.
La condicin es fundamental en esta opcin y normalmente aludir a un campo ndice (clave principal o nica), de modo que sea un solo registro el que cumpla la condicin. Podra ser el caso, en nuestro ejemplo, del campo DNI que por su unicidad garantizara que la modificacin solamente va a afectar a uno solo de los registros. El ejemplo siguiente nos permitir hacer modificaciones de este tipo en la tabla deomodat2. Observa el cdigo fuente y vers que mediante un simple recurso JavaScript, el script que realiza la modificacin nos reenva al formulario con un mensaje de confirmacin de la modificacin. En este primer caso utilizaremos las instrucciones de modificacin mediante procesos
Ejecutar la modificaccin Ver cdigo formulario Ver cdigo script
Aqu tienes el mismo ejemplo del supuesto anterior modificando a programacin mediante objetos el tratamientos de las instrucciones de gestin de la base de datos
Ejecutar la modificaccin Ver cdigo formulario Ver cdigo script
En el ejemplo hemos incluido un campo BLOB para incluir la imagen, insertando tambin campos para recoger su nombre, su tamao (en bytes), su formato (el tipo de fichero transferido) as como un campo autoincremental. No es otra cosa que el ejemplo incluido en esta pgina adaptado la nueva extensin de comunicacin entre PHP y MySQL.
<?php #definimos una variable con el NOMBRE QUE QUEREMOS DAR A LA TABLA $tabla="fotos"; /* incluimos los datos de conexin al servidor MySQL */ include("mysqli.inc.php"); /****** Programacin por procesos ***********/ #conexion y seleccion de base de datos $conexion=@mysqli_connect($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); #escribimos la sentencia que crea la tabla $crear="CREATE TABLE IF NOT EXISTS $tabla ("; $crear.="num_ident INT(10) unsigned NOT NULL AUTO_INCREMENT,"; $crear.="imagen BLOB NOT NULL, "; $crear.="nombre VARCHAR(255) NOT NULL DEFAULT '',"; $crear.="tamano VARCHAR(15) NOT NULL DEFAULT '',"; $crear.="formato VARCHAR(10) NOT NULL DEFAULT '',"; $crear.="PRIMARY KEY (num_ident))type=MyISAM"; #Creamos la cadena, comprobamos si esa instruccin devuelve # VERDADERO o FALSO # y dependiendo de ellos insertamos el mensaje de exito o fracaso if(mysqli_query ($conexion,$crear)) { echo "<h2> Tabla $tabla creada con EXITO </h2><br>"; }else{ echo "<h2> La tabla $tabla NO HA PODIDO CREARSE</h2><br>"; }; # cerramos la conexin... y listo... mysqli_close($conexion); ?>
Aqu tiene el cdigo fuente que te permitira crear la tabla fotos e insertar automticamente algunas imgenes de ejemplo.
Mediante procesos Mediante objetos
Transferencia de la imagen
El formulario para realizar la transferencia de la imagen no tiene particularidades. Es un formulario habitual para transferencia de ficheros. Lo nico reseable sera incluir un campo oculto en el que pudiera especificarse una restriccin en cuanto al tamao mximo permitido para cada imagen y que debe estar acorde con el tipo de campo utilizado en la tabla.
<FORM ENCTYPE="multipart/form-data" ACTION="ejemplo707.php" METHOD="post"> <INPUT type="hidden" name="lim_tamano" value="65000"> <p><b>Selecciona la imagen a transferir<b><br> <INPUT type="file" name="foto"><br> <p><b>Ttulo la imagen<b><br> <INPUT type="text" name="titulo"><br></p> <p><INPUT type="submit" name="enviar" value="Aceptar"></p> </FORM>
Ejemplo de transferencia de imagen
Al transferir imgenes jpg png el type MIME que reciba el servidor es distinto segn el navegador que se utilice para hacer la transferencia. Aqu debajo, en el cdigo fuente del script que actualiza la base de datos, tienes los nombres de esos tipos asociados a los navegadores ms usuales.
<?php $foto_name= $_FILES['foto']['name']; $foto_size= $_FILES['foto']['size']; $foto_type= $_FILES['foto']['type']; $foto_temporal= $_FILES['foto']['tmp_name']; $lim_tamano= $_POST['lim_tamano']; $foto_titulo= $_POST['titulo']; /* limitamos los formatos de imagen admitidos a: png que segun del navegador que ulicemos puede ser: en IE image/x-png en Firefox y Mozilla image/png jpg que puede tener como tipo en IE image/pjpeg en Firefox y Mozilla image/jpeg gif que tiene como tipo image/gif en todos los navegadores Mira los comentarios al margen sobre la variable $extensin */ if ($foto_type=="image/x-png" OR $foto_type=="image/png"){ $extension="image/png"; } if ($foto_type=="image/pjpeg" OR $foto_type=="image/jpeg"){ $extension="image/jpeg"; } if ($foto_type=="image/gif" OR $foto_type=="image/gif"){ $extension="image/gif"; } # condicionamos la insercin a que la foto tenga nombre, # un tamao distinto de cero y menor de lmite establecido # en el formulario y que la variable extensin sea no nula if ($foto_name != "" AND $foto_size != 0 AND $foto_titulo !='' AND $foto_size<=$lim_tamano AND $extension !=''){ /*reconversion de la imagen para meter en la tabla abrimos el fichero temporal en modo lectura "r" binaria"b"*/ $f1= fopen($foto_temporal,"rb"); #leemos el fichero completo limitando # la lectura al tamao de fichero $foto_reconvertida = fread($f1, $foto_size); #anteponemos \ a las comillas que pudiera contener el fichero # para evitar que sean interpretadas como final de cadena $foto_reconvertida=addslashes($foto_reconvertida); # abrimos la base de datos y escribimos las intrucciones de insercin # en el campo BLOB insertaremos la foto_reconvertida $tabla="fotos"; include("mysqli.inc.php"); $conexion=@mysqli_connect($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $meter="INSERT INTO ".$tabla; $meter .=" (num_ident, imagen, nombre, tamano, formato) "; $meter .=" VALUES('','$foto_reconvertida','$foto_titulo',"; $meter .= "$foto_size, '$extension')"; if (@mysqli_query($conexion,$meter)){ print "Foto guardada en la tabla"; }else{ print "Ha habido un error al guardar la foto"; } }else{ echo "<h2>No ha podido transferirse el fichero</h2>";
} mysqli_close($conexion); ?>
Hay otro aspecto a tener en cuenta. Esa discriminacin de tipos se plantea nicamente cuando Apache recibe una transferencia. Cuando se visualiza un contenido las cabeceras tipo de contenido (header("content-type: xx")) pueden ser las mismas para todos los navegadores. Esa es la razn por la que a la hora de incluir el formato en la tabla utilizamos image/jpg, image/gif o image/png.
Visualizacin de imgenes
La lectura de una imagen utiliza solo dos instrucciones. Incluir la cabecera Header en el que se indica el tipo de contenido (el famoso nombre MIME de la imagen) y luego imprimir el contenido del campo. Pero (por aquello de que header debe ir incluida en el script antes que cualquier otra salida) si pretendemos incluir en una pgina algo ms que una imagen tendremos que invocar esas dos funciones, de forma independiente, para cada una de ellas. Por esa razn al desarrollar el ejemplo que permite visualizar todas las imgenes de la tabla hemos tenido que incluir un script que va leyendo la tabla que contiene las imgenes para extraer los campos informativos y a la hora de ver la imagen hemos de recurrir a la misma tcnica que se utilizaba para ver las imgenes dinmicas. Es decir, poner una etiqueta de imagen de las de HTML pero -en vez de escribir el nombre de la imagen- poniendo incluyendo como nombre el del script que las visualiza y pasndole el nmero (valor del campo autoincremental) de la imagen que pretend visualizar.
<?php $numero=$_REQUEST['n']; $tabla="fotos1"; include("mysqli.inc.php"); $conexion=@mysqli_connect($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sacar = "SELECT * FROM ".$tabla." WHERE (num_ident=$numero)" ; $resultado = mysqli_query($conexion,$sacar); while ($registro = mysqli_fetch_assoc($resultado)){ $tipo_foto=$registro['formato']; header("Content-type: $tipo_foto"); echo $registro['imagen']; } mysqli_close($conexion); ?>
Ver imgenes guardadas
El JavaScript que asigna la transparencia a las imgenes en formato png las identifica buscando la coincidencia de los tres ltimos caracteres del nombre de la imagen con la extensin png. Cuando se trata de imgenes dinmicas el nombre de la imagen coinciden con el nombre de la llamada al script que se utiliza para su visualizacin. Por eso, para advertir a JavaScript de que se trata de una imagen png hemos incluido el condicional que puedes ver en el ejemplo. De esa forma, cuando se trata de una imagen en este formato incluimos en la peticin una variable con el valor png de forma que pueda ser reconocida por pngfix.js y aplicada la transparencia requerida. Script para leer la base de datos
<html> <head> <!-- al margen te comentamos la razn por la que --> <!-- se incluyen estas lneas en rojo --> <!--[if IE ]> <script type="text/javascript" src="pngfix.js"></script> <![endif]--> </head> <body> <? $base="ejemplos"; $tabla="fotos1"; include("mysqli.inc.php"); $conexion=mysqli_connect($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); $sacar = "SELECT * FROM ".$tabla; $resultado = mysqli_query($conexion,$sacar); while ($registro = mysqli_fetch_assoc($resultado)){ print "<center>Titulo de la imagen: ".$registro['nombre']."<br>"; /* la inclusin de este condicional obedece a los problemas que plantea la visualizacin de las transparencias de las imgenes png en Internet Explorer. Al margen justificamos las razones de su inclusin */ if($registro['formato']=="image/png"){ print "<img src='ver_foto.php?n=".$registro['num_ident']."&v=png'><br>"; }else{ print "<img src='ver_foto.php?n=".$registro['num_ident']."'><br>"; } print "Tamao de la imagen: ".$registro['tamano']." bytes </center>"; } mysql_close(); ?> </body> </html>
Ver imgenes guardadas
# escribimos la cadena que contiene la sentencia de creacin de la nueva tabla $crear="CREATE TABLE $tabla ("; $crear.="Contador TINYINT(8) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,"; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; $crear.="Nacimiento DATE DEFAULT '1970-12-21', "; $crear.="Hora TIME DEFAULT '00:00:00', "; $crear.="Sexo Enum('M','F') DEFAULT 'M' not null, "; $crear.="Fumador CHAR(0) , "; $crear.="Idiomas SET(' Castellano',' Francs','Ingls', ' Alemn',' Blgaro',' Chino'), "; $crear.=" PRIMARY KEY(DNI), "; $crear.=" UNIQUE auto (Contador)"; $crear.=")"; # esta es la nica diferencia con el proceso de # creacin de tablas MyISAM $crear.=" Type=InnoDB"; /* tenemos completa la sentencia MYSQL solo falta ejecutarla crear la conexin y ejecutarla */ /*incluimos los parmetros de conexin */ include('mysqli.inc.php'); /* incluimos dos opciones de proceso y de programacion orientada a objetos. Podemos ejecutar los ejemplos pasado mediante el metodo GET el tipo elegido. */ if(!empty ($_GET['tipo'])){ $tipo_script=$_GET['tipo']; }else{ $tipo_script="objetos"; } /*En caso de tipo proceso utilizaramos esto */ if ($tipo_script=="proceso"){ /****** Programacin mediante procesos ***********/ #conexion, seleccin de base de datos y verificacion de errores segun ejemplos anteriores $conexion=@mysqli_connect ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); if(!mysqli_connect_errno()==0){ print "<Mbr>No ha podido realizarse la conexin mediante procesos<br>"; print "Error nmero: ". mysqli_connect_errno()." equivalente a: ". mysqli_connect_error(); exit(); } # Creacin. Los parmetros requieren el orden aqu indicado al revs del caso mysql if(mysqli_query($conexion,$crear)){ print "La tabla ha sido CREADA"; }else{ print "<br>No ha podido crearse la base de datos mediante procesos<br>"; print "Error : ". mysqli_error($conexion); exit(); } mysqli_close($conexion); } /* en caso de programacion orientada a objetos */
if ($tipo_script=="objetos"){ #conexion, seleccin de base de datos y verificacion de errores segun ejemplos anteriores $objeto=@new mysqli ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); if(!$objeto->connect_errno==0){ print " No ha podido realizarse la conexin mediante objetos<br>"; print "Error nmero: ". $objeto->connect_errno." equivalente a: ". $objeto>connect_error; exit(); } if($objeto->query($crear)){ print "La tabla ha sido CREADA"; }else{ print "<br>No ha podido crearse la tabla mediante objetos<br>"; print "Error : ". $objeto->error; exit(); } $objeto->close(); } ?> Cuidado! Bajo Windows, al crear una base de datos o tabla InnoDB el nombre de la misma aparecer en minsculas independientemente de la sintaxis que hayamos utilizado en su creacin. Para prever posibles conflictos al ejecutar los scripts en diferentes plataformas utilizaremos minsculas para los nombres de tablas.
Una vez creadas, las tablas InnoDB se comportan a efectos de uso exactamente igual que las que hemos venido utilizando en las pginas anteriores. No es preciso hacer ningn tipo de modificacin en la sintaxis. Por tanto, es totalmente vlido todo lo ya comentado respecto a: altas, modificaciones, consultas y bajas.
Las transacciones
Uno de los riesgos que se plantean en la gestin de bases de datos es que pueda producirse una interrupcin del proceso mientras se est actualizando una o varias tablas. Pongamos como ejemplo el cobro de nuestra nmina. Son necesarias dos anotaciones simultneas: El cargo en la cuenta del organismo pagador y el abono en nuestra cuenta bancaria. Si se interrumpiera fortuitamente el proceso en el intermedio de las dos operaciones podra darse la circunstancia de que apareciera registrado el pago sin que se llegaran a anotar los haberes en nuestra cuenta. Las transacciones evitan este tipo de situaciones ya que los datos se registran de manera provisional y no se consolidan hasta que una instruccin confirme que esas anotaciones tienen carcter definitivo. Hemos de tener muy presente que para utilizar este tipo de opciones es imprescindible que las tablas sean del tipo InnoDB.
SELECT @@autocommit
qu siguiendo el tratamiento clsico de las consultas nos devolver el valor TRUE (1) o FALSE (0) de su estado actual. Su valor por defecto es TRUE y las eventuales modificaciones que podamos hacer en nuestros script solo persisten hasta la finalizacin de la ejecucin del mismo. La modificacin de su estado requiere de una de estas funciones: mysqli_autocommit($conexion,BOOLEANO ) o $objeto->autocommit(BOOLEANO )
Siendo $conexion el identificador de conexin (programacin mediante procesos) y $objeto el identificador del objeto mysqli (programacin orientada a objetos. El valor BOOLEANO puede ser TRUE o FALSE. Como es lgico para poder utilizar las transacciones es necesario que ese valor sea FALSE. Una vez configurado autocommit como false las sucesivas sentencias, sean simples, mltiples como preparadas, no se registrarn en la tabla hasta que no se incluya una orden explcita de hacerlo. Esa orden requiere el uso de una de ests dos funciones: mysqli_commit($conexion ) o $objeto->commit()
sentencias que advierte a MySQL (en modo procesos y objetos respectivamente) que ha finalizado la transaccin y que S debe hacer efectivos todos los cambios incluidos en ella. Si se optara por NO hacer efectivos los cambios habra que utilizar: mysqli_rollback($conexion ) o $objeto->rollback()
Cuidado! Cuando una instruccin modifica la condicin de autocommit ese valor no recupera su valor por defecto (true) hasta que no se incluya una modificacin explcita de su valor o hasta que finalice la ejecucin del script actual.
La integridad referencial
Elementos necesarios para la integridad referencial
La integridad referencial ha de establecerse siempre entre dos tablas. Una de ellas ha de comportarse como tabla principal (suele llamarse tabla padre y la otra sera la tabla vinculada tabla hijo. Es imprescindible: Que la tabla principal tenga un ndice primario (PRIMARY KEY) Que la tabla vinculada tenga un ndice (no es necesario que sea ni nico ni primario) asociado a campos de tipo idntico a los que se usen para ndice de la tabla principal. Si observas el cdigo fuente del ejemplo que tienes aqu debajo podrs observar que utilizamos el nmero del DNI (nico para alumno) como elemento de vinculacin de la tabla de datos personales con la que incluye las direcciones.
donde el campo de vinculacion ha de ser un ndice (no es necesario que sea PRIMARY KEY ni UNIQUE) y donde Indice primario de la tabla principal ha de ser un ndice primario (PRIMARY KEY) de la tabla principal. Debe haber plena coincidencia (tanto en tipos como contenidos) entre ambos ndices.
<?php $tabla1="principal"; $tabla2="vinculada"; /*incluimos los parmetros de conexin */ include('mysqli.inc.php'); /****** Programacin mediante procesos ***********/ #conexion, seleccin de base de datos y verificacion de errores segun ejemplos anteriores $conexion=@mysqli_connect ($cfg_servidor,$cfg_usuario,$cfg_password,$cfg_basephp1); # creacin de la tabla principal type InnoDB $crear="CREATE TABLE IF NOT EXISTS $tabla1 ("; $crear.="DNI CHAR(8) NOT NULL, "; $crear.="Nombre VARCHAR (20) NOT NULL, "; $crear.="Apellido1 VARCHAR (15) not null, "; $crear.="Apellido2 VARCHAR (15) not null, "; # el indice primario es imprescindible. Recuerda que debe # estar definido sobre campos NO NULOS $crear.=" PRIMARY KEY(DNI) "; $crear.=")"; $crear.=" Type=InnoDB"; # creamos la tabla principal comprobando el resultado if(@mysqli_query ($conexion,$crear)){ print "La tabla ".$tabla1." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla1." ha habido un error<br>";
} # crearemos la tabla vinculada $crear1="CREATE TABLE IF NOT EXISTS $tabla2 ("; $crear1.="IDENTIDAD CHAR(8) NOT NULL, "; $crear1.="calle VARCHAR (20), "; $crear1.="poblacion VARCHAR (20), "; $crear1.="distrito VARCHAR(5), "; # creamos el ndice (lo llamamos asociador) para la vinculacin # en este caso no ser ni primario ni nico # Observa que el campo IDENTIDAD de esta tabla CHAR(8) # es idntico al campo DNI de la tabla principal $crear1.=" KEY asociador(IDENTIDAD), "; #establecemos la vinculacin de ambos ndices $crear1.=" FOREIGN KEY (IDENTIDAD) REFERENCES $tabla1(DNI) "; $crear1.=") TYPE = INNODB"; # creamos (y comprobamos la creacin) la tabla vinculada if(@mysqli_query ($conexion ,$crear1)){ print "La tabla ".$tabla2." ha sido creada<br>"; }else{ print "No se ha creado ".$tabla2." ha habido un error<br>"; } mysqli_close($conexion); ?>
Aqu tienes el ejemplo en ambas modalidades
Ejecutar Modo procesos Ver cdigo fuente Modo procesos Ejecutar Orientado a objetos Ver cdigo fuente Orientado a objetos
Modificacin de estructuras
La modificacin de estructuras en tablas vinculadas puede hacerse de forma idntica a la estudiada para los casos generales de MySQL siempre que esas modificaciones no afecten a los campos mediante los que se establecen las vinculaciones entre tablas. Aqu tienes un ejemplo en se borran y aaden campos en ambas tablas. Como puedes ver la sintaxis es exactamente la misma que utilizamos en temas anteriores.
Ver cdigo fuente Modo procesos Ver cdigo fuente Orientado a objetos
Conocido el valor de parmetro anterior el proceso de borrado del vnculo actual requiere la siguiente sintaxis: ALTER TABLE nombre de la tabla DROP FOREIGN KEY parametro
Cuando se trata de aadir un nuevo vnculo con una tabla principal habremos de utilizar la siguiente sentencia: ALTER TABLE nombre de la tabla ADD [CONSTRAINT parametro] FOREIGN KEY parametro REFERENCES tabla principal(clave primaria)
El parmetro CONSTRAIT (encerrado en corchetes en el prrafo anterior) es OPCIONAL y solo habra de utilzarse en el caso de que existiera ya una vinculacin previa de esa tabla. En estos ejemploS determinaremos el valor de CONSTRAINT borraremos un campo asociado de una tabla vinculada y posteriormente crearemos un nuevo campo idntico al eliminado.
Ejecutar Modo procesos Ver cdigo fuente Modo procesos Ejecutar Orientado a objetos Ver cdigo fuente Orientado a objetos
Las tablas vinculadas s permiten el borrado y una vez que stas ya han sido eliminadas (o quitada la vinculacin) ya podrn borrarse sin problemas las tablas principales. El orden de borrado (si ambas pretenden borrarse desde el mismo script)es importante. Primero se borra la vinculada y luego la principal.
Esta condicin (es la condicin por defecto de MySQL y no es preciso escribirla) indica a MySQL que interrumpa el proceso de borrado y d un mensaje de error cuando se intente borrar un registro de la tabla principal cuando en la tabla vinculada existan registros asociados al valor que se pretende borrar. ON DELETE NO ACTION
Cuando se especifica esta opcin, al borrar un registro de la tabla principal se borrarn de forma automtica todos los de la tabla vinculada que estuvieran asociados al valor de la clave fornea que se trata de borrar. Con ello se conseguira una actualizacin automtica de la segunda tabla y se mantendra la identidad referencial. ON DELETE SET NULL
Con esta opcin, al borrar el registro de la tabla principal no se borraran los que tuviera asociados la tabla secundaria pero tomaran valor NULL todos los ndices de ella coincidentes con la clave primaria de la tabla principal. Para el caso de ON UPDATE las opciones son estas: ON UPDATE RESTRICT ON UPDATE CASCADE ON UPDATE SET NULL
Cuidado! El uso de la opcin SET NULL requiere que el campo indicado en FOREIGN KEY permita valores nulos. Si est definido con flag NOT NULL (como ocurre en los ejemplos que tienes aqu) dara un mensaje de error. Al incluir ON DELETE y ON UPTADE (si se incluyen ambas) han de hacerse por este mismo orden. Si se cambiara este orden dara un mensaje de error y no se ejecutaran.
Automatizacin de procesos
En estos ejemplos haremos un proceso partiendo de cero. Borraremos las eventuales tablas preexistentes, crearemos dos tablas vinculadas, insertaremos algunos datos y posteriorme realizaremos una actualizacin en cascada.
Ejecutar Ver cdigo fuente Ejecutar Ver cdigo fuente
Modo procesos
Modo procesos
Orientado a objetos
Orientado a objetos
Como habrs podido observar una consulta con el cdigo adecuado WHERE Nombre='' or '34=34' muestra la vulnerabilidad y devuelve todos los registros contenidos en la tabla por las mismas razones ya comentadas al estudiar MySQL. Para evitar la posibilidad de ese efecto indeseado (inyeccin de cdigo) cuando utilizamos MySQLi, PHP dispone de las funcin: mysqli_real_escape_string($conexion,cadena) o $objeto->real_escape_string(cadena) que hace una llamada a la librera MySQL del mismo nombre y para que escape los caracteres especiales contenidos en lacadena de forma que sea mucho ms seguro su uso a travs de mysql_query(). Los caracteres que son escapados son los siguientes:\x00, \n, \r, \, ', " y \x1a. Se convertiran en: \\x00, \\n, \\r, \\\, \', \" y \\x1a con lo cual la cadena ' or '34=34 se convertira en \' or \'34=34 y la clasula anteriormente comentada se convertira en WHERE (Nombre='\' or \'34=34') con lo cual ya no se producira el efecto indeseado y se evitara el riesgo de uso inadecuado.
Ejecutar consulta Mediante procesos Ver cdigo fuente Mediante procesos Ejecutar consulta Mediante objetos Ver cdigo fuente Mediante objetos
Cuidado! El uso de la funcin mysqli_real_escape_string() requiere como parmetro un identificador de conexin. Por lo tanto es imprescindible que antes de utilizarla se haya establecido una conexin con el servidor MySQL. De igual manera, cuando se trata de programacin orientada a objetos, real_escape_string() es un mtodo y en consecuencia es requisito inprescindible la preexistencia del objeto antes de su utilizacin.
Aunque los desarrolladores de PHP anuncian su prxima desaparicin, en la actualidad hay en el fichero php.ini una directiva llamadamagic_quotes_gpc cuyo valor por defecto es Off. Si cambiramos esa directiva a On (o si usramos un servicio externo que la tuviera configurada de esta forma) todos los datos recibidos por medio de los mtodos GET o POST seran tratados por la funcin: addslashes(cadena) que devuelve la cadena despus de haber escapado los carcteres ',", \ y NUL (el byte NULL). La accin de addslashes puede deshacerse utilizando la funcin stripslashes(cadena_escapada) que quita los carcteres de escape aadidos por addslashes devolviendo la cadena original. Para comprobar como est configurada la directiva magic_quotes_gpc disponemos de la funcin: get_magic_quotes_gpc() que devuelve un valor booleano. True si est configurada como On y False en caso de estarlo como Off.
Filtrado de cdigo
Mediante un proceso como el que puedes ver en el cdigo fuente que se incluye a continuacin puede realizarse un filtrado de los eventuales intentos de inyeccin de cdigo. Su funcionamiento es el siguiente: Leemos toda la informacin que se recibe en las variables superglobales $_GET y $_POST. Recorremos los arrays que recogen esos resultados sustituyendo sus valores por los obtenidos de la aplicacin de una funcin que realiza el filtrado. La funcin que realiza el filtrado comprueba el estado de magic_quotes. Caso de estar configuradas con On revierte los caracteres escapados para impedir que se dupliquen los carcteres de escape. Comprueba si es numrico el valor recibido y en caso de serlo lo devuelve sin ninguna modificacin. Si el valor recibido no es numrico aplica la funcin mysqli_real_escape_string y devuelve el resultado dentro de unas comillas simples. De esta forma podramos despreocuparnos de poner comillas al valor de la variable en la clasula WHERE. Si se trata de un nmero no las requiere y si se trata de una cadena el valor recibido ya las incluye.
<?php if(is_array($_GET)){ foreach ($_GET as $_GET_indice=>$_GET_valor){ $_GET[$_GET_indice]=filtro_seguridad($_GET_valor); } } if(is_array($_POST) ){ foreach ($_POST as $_POST_indice=>$_POST_valor){ $_POST[$_POST_indice]= filtro_seguridad($_POST_valor); } } function filtro_seguridad($valor){ /* comprueba si estn activas las magic_quotes y, en caso de estarlo revierte su accin mediante stripslashes */ if (get_magic_quotes_gpc()) $valor = stripslashes($valor); /* Abrimos una conexin con MySQL requerida para aplicar mysqli_real_escape_string */ $conexion=mysqli_connect("localhost","pepe","pepa"); /* con la certeza de que estamos ante la cadena original aplicamos la funcin mysql_real_escape_string a todas las cadenas no numricas */ if (!is_numeric($valor)) $valor = "'" .mysqli_real_escape_string($conexion,$valor) . "'"; /* cerramos la conexion y devolvemos el resultado*/ mysqli_close($conexion); return $valor; } ?>
Este es un ejemplo de utilizacin de procedimiento anterior
Ejecutar consulta Mediante procesos Ver cdigo fuente Mediante procesos
En el caso de optar por la programacin orientada a objetos el script anterior debera tener esta sintaxis:
<?php if(is_array($_GET)){ foreach ($_GET as $_GET_indice=>$_GET_valor){ $_GET[$_GET_indice]=filtro_seguridad($_GET_valor); } } if(is_array($_POST) ){ foreach ($_POST as $_POST_indice=>$_POST_valor){ $_POST[$_POST_indice]= filtro_seguridad($_POST_valor); } }
function filtro_seguridad($valor){ /* comprueba si estn activas las magic_quotes y, en caso de estarlo revierte su accin mediante stripslashes */ if (get_magic_quotes_gpc()) $valor = stripslashes($valor); /* Abrimos una conexin con MySQL requerida para aplicar mysqli_real_escape_string */ $objeto_filtro=new mysqli("localhost","pepe","pepa"); /* con la certeza de que estamos ante la cadena original aplicamos la funcin mysql_real_escape_string a todas las cadenas no numricas */ if (!is_numeric($valor)) $valor = "'" .$objeto_filtro->real_escape_string($valor) . "'"; /* cerramos la conexion y devolvemos el resultado*/ $objeto_filtro->close(); return $valor; } ?>
Este es un ejemplo de utilizacin de procedimiento anterior
Ejecutar consulta Mediante objetos Ver cdigo fuente Mediante objetos
Como podrs observar hemos intentado incluir una pequea miscelnea de elementos HTML utilizando estilos CSS en algunos casos. Las nicas novedades (si es que lo son para t) son las nuevas formas de utilizacin la etiqueta <object> que parece tener una gran proyeccin futura ya que este tipo de elemento permite utilizar una sintaxis similar para los diferentes elementos. Compatible con las mayora de los navegadores modernos (la estandarizacin en trminos absolutos me temo que es una gran utopa) y utilizando <object data="ruta_nombre_y_extension" type="tipo_mime"> De esta forma, <object id="foto_objeto" data="./images/bocadillo.gif" type="image/gif"></object>> nos permite incluir una imagen de forma alternativa a la clsica de: <img id="foto_objeto" src="./images/bocadillo.gif" />. De igual forma y tan slo modificando el tipo de objeto hemos incluido una animacin flash usando <object type="application/x-shockwave-flash" data="./videos/trubia.swf"> y tambin un sonido por medio de <object type="audio/x-wav" data="data/test.wav"></object> e incluso hemos podido utilizar, como opcin alternativa al clsicoIFRAME el objeto <object id="web" data="http://www.rinconastur.com" type="text/html"></object> ahora con tipo text/html. Como quiera que existen una gran variedad de tipos MIME en este enlace tiene una chuleta en la que se incluyen una buena parte de las extensiones de ficheros existentes y los tipos MIME asociados.
Cuidado! He vuelto atrs para corregir el ejemplo anterior y a la vez advertirte de algo de relativa importancia. Parece que la estadarizacin es algo absolutamente imposible. Los quebraderos de cabeza son continuos y muchas veces nos obligan a recurrir a algunas chapuzas. Una de ellas sera tener la precaucin de incluir dentro de una etiqueta div losobject destinados a contener pginas web. Es decir, en vez de escribir algo como: <object id="web" data="http://www.rinconastur.com" type="text/html"></object> procura escribir esto: <div id="chapuza_para_IE"> <object id="web" data="http://www.rinconastur.com" type="text/html"></object> </div> Puede parecer (o ser) ridculo pero no encontr una opcin mejor para resolver un problema que se me plante un poco ms adelante. Misterios de la informtica! Me hizo recordar un pseudodespido del que fu vctima hace ya unos cuantos aos. Tard ms de un mes en darme cuenta que en una opcin de QuarkXpress no era lo mismo 90 que la suma algebraica (-90+180)!Misterios ...!
Cuidado! La normalizacin o estandarizacin parece ser una utopa en el mundo de los navegadores y el JavaScript. Si abres la pgina del prrafo anterior aqu est el enlace con distintos navegadores podrs observar que los resultados de pulsar sobre los enlaces que contiene son distintos en cada uno de ellas. Podrs ver, por ejemplo, que en Internet Explorer no van a aparecerte alusiones a los mtodos que incluyen los objetos. Tambin podrs observar que las propiedades, en incluso los objetos contenidos en cada uno de los objetos, no son exactamente los mismos. La
compatibilidad entre los diferentes navegadores sigue requiriendo autntico encaje de bolillos. Quiz algn da... se normalizarn los navegadores.
Para nuestros fines uno de los objetos ms importantes es window.document.body como todos los objetos JavaScript que vayamos manejando incluye una serie de propiedades y mtodos que puedes ver enumeradas en el enlace de igual nombre que hay en este documento. El objeto window.document.body incluye otro objeto llamado window.document.body.style cuyas propiedades son las diferentes opciones de estilos aplicables al body. Cuales son esas propiedades? La lista es larga y bastante similar a la utilizada en las hojas de estilo pero cuidado! que la sintaxis no es la misma. Por ejemplo lo que en CSS (las hojas de estilo en cascada) se define como background-color se corresponde con una propiedad del objeto style de JavaScript llamada backgroundColor. Para facilitarte las cosas en este enlacetienes la lista de las diferentes propiedades relacionadas con los estilos. Veamos ahora un poco de cdigo JavaScript relacionado con este asunto. En PHP el cdigo lo delimitamos mediante <?php y ?>. En JavaScript es bastante similar aunque aqu se delimita por medio de las etiquetas <script type="text/javascript"> y </script> El tratamiento de las propiedades de los objetos es similar al que usamos en PHP con la diferencia que las -> son reemplazadas aqu. y que, a diferencia de PHP hay una serie de objetos (body entre ellos) que no hace falta instanciar porque se crean de forma automtica. Por tanto para modificar una propiedad bastara con escribir algo as: window.document.body.style.backgroundColor="nuevo_color". Eso es lo que puedes ver en estos ejemplos. Pero fjate en los dos primeros. Tambin aqu el navegador hace una lectura secuencial del documento y si instanciamos un objeto que an no ha sido creado (es lo que ocurre en el primer ejemplo) no habr manera de que se modifique la pretendida propiedad.
<html> <head> <title>Pruebas del body</title> <script type="text/javascript"> window.document.body.style.backgroundColor="#ffff00"; </script> </head> <body> Te has precipidado. Me mandaste cambiar el color del body antes de que el body existiera. </body> </html>
Ver ejemplo
<html> <head> <title>Pruebas del body</title> </head> <body> <script type="text/javascript"> window.document.body.style.backgroundColor="#ffff00"; </script> Ahora si me pondr amarillo. Las cosas en su sitio. Los javascript tambin. </body> </html>
Ver ejemplo
Vamos un poco a salto de mata pero como todos los lenguajes tienen una gran similitud pienso que no resulta difcil de entender este nuevo ejemplo. Tambin existen funciones en JavaScript, tambin la sintaxis es: function nombre_de_la_funcion(){ .... ... instrucciones .... .... }
Como ocurre en PHP y en todos los dems lenguajes las funciones no se ejecutan hasta que no son invocadas (eso permite incluirlas en cualquier parte del documento) y tambin aqu se invocan escribiendo nombre_de_la_funcion(). Hay una diferencia (puedes verla en el ejemplo) y es que en el caso de JavaScript la ejecucin de la funcin puede asociarse a un evento. Un evento no es otra cosa segn la RAE que un acaecimiento, una cosa que sucede. Y ese es su significado. Cuando acaece que se carga el body de la pgina (onLoad) es cuando se ejecuta automticamente la funcin.
<html> <head> <title>Pruebas del body</title> <script type="text/javascript"> function cambia_fondo(){ window.document.body.style.backgroundColor="#ffff00"; } </script> </head> <body onLoad="cambia_fondo()"> Ahora me es dicho: cuando cambies cargues el body (onLoad) ejecuta la funcin cambia_fondo. Soy obediente y lo hago </body> </html>
Ver ejemplo
Los ejemplos anteriores aluden al objeto style contenido en body. Pero body tiene, adems sus propiedades (algunas modificables otras no) que tambin se pueden acceder de forma fcil. Aqu tienes un ejemplo en el que hemos incluido una novedad. Ahora la funcin se ejecuta pulsando un enlace clsico en el que hemos sustituido el nombre de la nueva pgina (lo habitual en los enlaces) por esto otro:javascript:nombre_de_la_funcion(). Ahora, cuando pulsemos en el enlace se ejecutar la funcin. Podrs ver como la funcin alert() abre una ventanita informativa sobradamente conocida en la que puede leerse el valor de lo contenido en su parntesis.
<html> <head> <title>Pruebas del body</title> <script type="text/javascript"> function informame(){ alert(window.document.body.clientWidth); } </script> </head> <body> Si <a href="javascript:informame()">pulsas aqu</a> podrs conocer el ancho de esta ventana. Si modificas su tamao y vuelves a pulsar vers que la medida cambia. </body> </html>
Ver ejemplo
La identificacin de cada uno de los elementos de una pgina podra complicarse a medida que la pgina va incluyendo contenidos. JavaScript ha ido evolucionando a lo largo del tiempo. Los primeros navegadores con JavaScript permitan acceder slo a ciertos tipos de objetos del contenido del documento que son conocidos como colecciones y que se identifican como document.anchors (anclas),document.forms (formularios), document.images (imgenes), document.links (enlaces), doc ument.applets (applets) y document.embeds(objetos incrustados), estos dos ltimos ya han caido en absoluto desuso. Como quiera que en un mismo documento puede haber varios objetos de la misma coleccin (varias imgenes o varios formularios por poner un ejemplo) la forma de referirse a ellos era (y sigue siendo ya que los navegadores actuales mantienen esta forma de acceso a estos tipos de objetos) utilizar lo que en PHP llamaramos un ndice escalar de forma que sintaxis del tipo document.images[0] odocument.images[4] haran alusin a la primera (empieza a numerar desde cero) y la quinta (por la misma razn) de las imgenes contenidas en el documento contadas, como se deca en lo crditos de las pelculas, por orden de aparicin.
Tambin es factible aludir a los diferentes elementos por medio de id de modo que si en la etiqueta de una imagen incluimos algo como: <img id="la_foto" src="...." /> javaScript la identificar cuando escribamos document.images['la_foto'] (fjate en las comillas que van dentro del corchete). En este ejemplo tienes algunas muestras de como hacer estas llamadas.
Ver ejemplo Ver cdigo fuente
Afortunadamente, nuestro ya famoso id pude suplir con creces las limitaciones de las colecciones. Ser la referencia utilizaremos en adelante. Bastar con que escribamos en JavaScript algo as como window.document.getElementById('identificador') para referirnos a el elemento HMTL cuya etiqueta de apertura incluya id="identificador". Para que JavaScript no tenga dudas bastar, tal como hemos comentado ya al principio de esta pgina, con que no repitamos los nombres de los identificadores a lo largo nuestro documento. Igual que ocurra con body, cada uno de los objetos window.document.getElementById('identificador') contiene un objeto style al que nos podremos referir utilizando la sintaxis: window.document.getElementById('identificador').style Si preferimos utilizar una sintaxis un poco menos farragosa podremos recurrir a objetos intermedios con denominaciones ms fciles. Por ejemplo: var variable1= window.document.getElementById('identificador'); y var variable2=variable1.style podramos hacer alusin mediante la variable variable1 al objeto cuyo id es identificador y a sus estilos mediante variable2. Probablemente resultara ms cmodo y ms corto.
<script type="text/javascript"> function cambia_aspecto(elemento, propiedad, valor){ if (elemento=="body"){ comando="document."+elemento+".style."+propiedad+"='"+valor+"'"; eval(comando); alert("Se ha ejecutado:\n\r"+comando); }else{ comando="document.getElementById('"+elemento+"').style."+propiedad+"='"+valor+"'"; eval(comando); alert("Se ha ejecutado:\n\r"+comando); } } </script>
Veamos su comportamiento. La llamada a la funcin incluye tres valores: elemento, propiedad y valor. Como elemento incluiremos el nombre del id cuya apariencia queremos modificar. Como propiedad pondremos el nombre de una de las propiedades de los objetos styleque tenemos enumeradas en este enlace y como valor incluiremos una cadena con el nuevo valor que pretendamos asignar a la propiedad.
En cualquiera de las opciones del condicional if (fjate que la sintaxis es idntica a la de PHP con la diferencia de que en JavaScript los nombres de variable no empiezan por $) hay una variable llamada comando que concatena textos entrecomillados con valores de variables. Podrs observar que en este caso el concatenador no es el . como ocurra en PHP sino el signo +. Con esa sintaxis la variable comando recogera cadenas tales como las que vas a poder leer al ejecutar el ejemplo. Una vez creada la variable ejemplo es necesario aplicarle la funcin JavaScript eval() que es quien realmente ejecuta la intruccin JavaScript contenida en la cadena comando. Hemos incluido una llamada a la funcin alert para poder visualizar el comando ejecutado por javascript. Es evidente que resulta innecesario desde un punto de vista prctico. Por ltimo quiz no est de ms aludir al condicional if. Cuando el objeto cuyo estilo que deseamos cambiar es body el objeto que recoge su estilo es: window.document.body.style cuando se trata de otros elementos que pueden no pertener a colecciones el objeto se identificara de forma distinta ya que habra que recurrir a:window.document.getElementById('nombre_del_elemento').style. La variable elemento nos permitir elegir uno u otro camino dependiendo del valor que contenga.
Cuidado! Cuando se trata de una misma ventana es indiferente utilizar la sintaxis window.document document. Habr otras situaciones en las que ser necesario tomar en consideracin ese asunto.
Una vez incluida la funcin en el documento solo nos faltara poner algn elemento que permita ejecutar esa funcin. En el ejemplo lo hemos hecho mediante los enlaces comentados anteriormente y cuya sintaxis podra ser similar a esta: <a href="javascript:cambia_aspecto('capa1','width','300px');">Cambiar ancho de la capa</a> De esta forma ya estaremos en condiciones de modificar el estilo de cualquier elemento de una pgina web tal como puedes comprobar en este ejemplo.
Ver ejemplo Ver cdigo fuente
Cuidado! La compatibilidad entre navegadores parece ser algo as como la cuadratura del crculo. Si ejecutas el ejemplo anterior en Internet Explorer vers que si cambia el color de fondo del radio. En otros navegadores no ocurrir lo mismo. Es cierto que la mayora de las opciones de estilo son compatibles entre navegadores pero... siempre hay algn pero en algn lugar que rompe la racha de compatibilidad.
La sintaxis de la funcin anterior tiene una alternativa mucho ms cmoda y simple que puedes visualizar aqu debajo:
Cuidado! Fjate que los nombres de las variables se incluyen sin comillas tanto en el parntesis como en el corchete. Si prentendemos incluir valores directamente dentro de esos elementos (parntesis y corchete) deberemos ponerlos entre comillas.
Como es lgico, el uso de una u otra funcin no altera para nada el resultado final. Aqu tienes la prueba.
Ver ejemplo
Una alternativa ms
Los objetos window.document.body.style y window.document.getElementById(nombre_del_elemento) disponen de otros mtodos que tambin pueden utilizarse para realizar los cambios de diseo comentados anteriormente. Se trata de: objeto.style.getAttribute('atributo') y de: objeto.style.setAttribute('atributo','valor') el primero de los mtodos nos devuelve una cadena conteniendo el valor actual de atributo mientras que el segundo nos permite efectuar modificar un atributo concreto .
<script type="text/javascript"> /* funcion para comprobar los valores actuales de una propiedad */ function comprueba_aspecto(elemento, propiedad){ if(elemento=='body'){ alert(window.document.body.style.getAttribute(propiedad)); }else{ alert(window.document.getElementById(elemento).style.getAttribute(propiedad); } } /* funcion para cambiar los valores actuales de una propiedad */ function cambia_aspecto(elemento, propiedad, valor){ if(elemento=='body'){ window.document.body.style.setAttribute(propiedad,valor); }else{ window.document.getElementById(elemento).style.setAttribute(propiedad,valor); } } </script>
Ver ejemplo Ver cdigo fuente
Modificar el valor de la propiedad agregando al resultado anterior la cadena que especifica el el tipo de unidades. Tendra una sintaxis similar a esta:propiedad=variable+'px'
<script type="text/javascript"> function recuenta(etiqueta){ /* en caso de que etiqueta sea nulo le asigna el valor del comodin * */ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; /* el objeto elementos recoger todos elementos cuyo nombre coincide con la variable etiqueta*/ var elementos = document.getElementsByTagName(etiqueta); /* la variable cadena recoger un literal y el nmero de elementos especificado por la propiedad elementos.length Los carcteres '\n\r' son saltos de lnea */ var cadena="Tengo "+elementos.length+'\n\r'; /* por medio de un bucle vamos aadiendo a la variable cadena los nombres de cada uno de los elementos contenidos en el objeto elementos e identificados por el subndice que indica su orden de creacin */ for (i=0;i<elementos.length;i++){ /* la propiedad tagName contiene el nombre del elemento */ cadena+=elementos[i].tagName+'\n\r'; } /* visualizamos la cadena resultante de la consulta */ alert(cadena); } </script>
Si ejecutas este ejemplo y pulsas el enlace Recuenta todos los elementos podrs ver la enumeracin ordenada de los nombres de cada uno de los elementos que contiene la pgina de ejemplo. Presta atencin a las diferentes etiquetas que visualiza y observa que, por ejemplo, contempla TBODY pese a no haber sido especificado expresamente dentro de la etiquet TABLE.
Ver ejemplo Ver cdigo fuente
La funcin anterior tiene su utilidad reducida a la enumeracin de los diferentes elementos de una pgina pero puede ser el soporte de estas otras funciones que si permiten llevar a cabo las pretendidas modificaciones masivas de los elementos de una pgina.
<script type="text/javascript">
/* la funcion recibe tres valores. El nombre de la etiqueta que pretendemos modificar el atributo que queremos cambiar o agregar a esas etiquetas y el valor que se pretende asignar al atributo */ function modifica(etiqueta,atributo,valor){ /* el condicional sustituye los valores nulos o vacios por el comodn */ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; /* por comodidad creamos el objeto elementos que incluir todos todos los objetos cuya etiqueta coincida con ese parmetro*/ var elementos = document.getElementsByTagName(etiqueta); /* por medio del bucle recorreremos secuencialmente cada uno de los elementos y mediante el mtodo setAttribute le aplicamos el nuevo valor al atributo indicado */ for (i=0;i<elementos.length;i++){ elementos[i].style.setAttribute(atributo,valor); } } /* esta otra funcion es la alternativa ya comentada de modificacin de una propiedad sin utilizar el mtodo setAttribute. Cualquiera de las dos funciones producir el mismo resultado */ function modifica1(etiqueta,atributo,valor){ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; var elementos = document.getElementsByTagName(etiqueta); for (i=0;i<elementos.length;i++){ elementos[i].style[atributo]=valor; } } </script>
Ver ejemplo Ver cdigo fuente
La utilizacin de hojas de estilo en cascada (CSS) lleva implcita la definicin de diferentes clases de estilos que son aplicados a los diferentes elementos de las pginas incluyendo dentro de sus etiquetas el atributo class="nombre_de_la_clase". Si en el ejemplo anterior hacamos un modificacin masiva de todas las etiquetas de un determinado tipo es posible que en momentos determinados tratemos de restringir esa modificacin a las etiquetas de una clase determinada. Esta posibilidad es propiciada por la propiedad objeto.className que nos devolver el nombre de la clase (si ha sido establecida) correspondiente a un objeto (etiqueta html) determinado. En caso de no haberse establecido esa propiedad tendr valor null o cadena vaca. Contemplar esta nueva posibilidad implicar readecuar las funciones del ejemplo anterior a este nuevo escenario.
<script type="text/javascript"> /* agregamos el nuevo parmetro clase a la funcin anterior */ function modifica(etiqueta,clase,atributo,valor){ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; var elementos = document.getElementsByTagName(etiqueta); for (i=0;i<elementos.length;i++){ /* establecemos la condicin de que para modificar el atributo coincida la clase con el valor recibido en ese parmetro o que la funcin haya sido invocada asignndole a clase un valor nulo o una cadena vacia en cuyo caso afectara a todos los elementos que no tuvieran una clase establecida*/ if(elementos[i].className==clase || clase==null || clase==''){ elementos[i].style[atributo]=valor; }
} } /* igual que en el ejemplo precedente esta funcin es una alternativa a la anterior */ function modifica1(etiqueta,clase,atributo,valor){ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; var elementos = document.getElementsByTagName(etiqueta); for (i=0;i<elementos.length;i++){ if (elementos[i].className==clase || clase==null || clase==''){ elementos[i].style[atributo]=valor; } } } </script>
Ver ejemplo Ver cdigo fuente
Aun puede darse un poco ms de versatilidad a la opcin de llevar a cabo modificaciones masivas de estilos. En los ejemplos anteriores la bsqueda de etiquetas y/o clases la realizabamos en document, es decir, a lo largo de toda la pgina visualizada en la ventana actual. Es posible que en determinadas situaciones nos interese realizar la bsqueda y modificacin slo en una parte del documento. Esa posibilidad nos obligara a llevar a cabo una nueva ampliacin en la funciones modificadoras que hemos venido manejando en los ejemplos anteriores. Aqu tienes el cdigo fuente.
<script type="text/javascript"> /* la funcion recibe ahora un quinto parmetro que hemos llamado contenedor*/ function modifica(contenedor,etiqueta,clase,atributo,valor){ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; /* si el contenedor es null o vacio entendemos que nos referimos a todo el documento */ if (contenedor==null || contenedor==''){ var elementos = document.getElementsByTagName(etiqueta); }else{ /*cuando el contenedor no es vacio entendemos que nos referimos al elemento de documento cuyo nombre identificador unico (id) es contenedor. La bsqueda de los elementos modificable la realizaremos dentro de esa parte del del documento (objeto cuya es etiqueta es etiqueta y contenidos dentro de un elemento cuyo id es el valor de la variable contenedor) */ var elementos=document.getElementById(contenedor).getElementsByTagName(etiqueta); } for (i=0;i<elementos.length;i++){ if(elementos[i].className==clase || clase==null || clase==''){ elementos[i].style[atributo]=valor; } } } /* las modificaciones son idnticas a las descritas para la funcin anterior que, como siempre, es una opcin alternativa a esta */ function modifica1(contenedor,etiqueta,clase,atributo,valor){ if ( etiqueta == null || etiqueta == ''){etiqueta = '*'}; if (contenedor==null || contenedor==''){ var elementos = document.getElementsByTagName(etiqueta); }else{ var elementos=document.getElementById(contenedor).getElementsByTagName(etiqueta); } for (i=0;i<elementos.length;i++){ if (elementos[i].className==clase || clase==null || clase==''){ elementos[i].style[atributo]=valor;
} } } </script>
Ver ejemplo Ver cdigo fuente
onMouseUp El evento se dispara en el momento en que se suelta cualquier botn del ratn encima del encima del texto del enlace Ejemplo: <a href="javascript:void(0)" onMouseUp="alert('Me disparo cuando sueltas botn el ratn sobre el texto')"></a>
tanbin maneja los siguientes: onChange El evento se dispara al salir de campo de texto depus de haber modificado su contenido Ejemplo: onFocus El evento se dispara al tomar el foco que equivale a situar el cursor dentro del campo de texto bien mediante el ratn o desplazndose entre campos por medio de la tecla de tabulacin Ejemplo: onBlur El evento se dispara al perder el foco que equivale a sacar el cursor del campo de texto bien mediante el ratn o desplazndose entre campos por medio de la tecla de tabulacin Ejemplo: onSelect El evento se dispara al seleccionar texto dentro del campo Ejemplo: onKeyPress El evento se dispara al mantener pulsada una tecla cuando el cursor est dentro del campo Ejemplo: onKeyUp El evento se dispara al soltar una tecla pulsada cuando el cursor est dentro del campo Ejemplo:
pulsa y suelta mantn pulsada selecciona una parte escribe aqui
onKeyDown El evento se dispara al pulsar una tecla cuando el cursor est dentro del campo Ejemplo:
pulsa una tecla
onKeyPress (leyendo el valor de la tecla pulsada) El evento se dispara al mantener pulsada una tecla cuando el cursor est dentro del campo y el alert muestra el resultado de ejecutar una funcin javascript que captura el valor de la tecla pulsada. Esa funcion tiene la forma siguiente:
<script type="text/javascript"> function captura_teclado(e){ var numero_de_tecla_pulsada; var caracter_de_la_tecla_pulsada; if(window.event){ //cosas de IE var numero_de_tecla_pulsada = e.keyCode //recoge en IE el valor ASCII de la tecla } else if(e.which){ // Cosas Netscape/Firefox/Opera var numero_de_tecla_pulsada = e.which //recoge valor ASCII en otros navegadores } /* obtiene el caracter correspondiente al codigo ASCII recogido */ caracter_de_la_tecla_pulsada = String.fromCharCode(numero_de_tecla_pulsada); /* devuelve el valor del caracter correpondiente a la tecla pulsada */ return caracter_de_la_tecla_pulsada; } </script>
Ejemplo (teclea dentro del campo):
El evento se dispara al hacer clic sobre la opcin Ejemplo: onFocus El evento se dispara al tomar el foco. Ejemplo: onBlur El evento se dispara al perder el foco. Ejemplo: Si No Si No Si No
tanbin maneja los siguientes: onChange El evento se dispara al salir de campo de texto depus de haber modificado su contenido
Ejemplo: onFocus El evento se dispara al tomar el foco que equivale a situar el cursor dentro del campo de texto bien mediante el ratn o desplazndose entre campos por medio de la tecla de tabulacin
Ejemplo: onBlur El evento se dispara al perder el foco que equivale a sacar el cursor del campo de texto bien mediante el ratn o desplazndose entre campos por medio de la tecla de tabulacin
Ejemplo: onKeyPress El evento se dispara al mantener pulsada una tecla cuando el cursor est dentro del campo
Ejemplo: onKeyUp El evento se dispara al soltar una tecla pulsada cuando el cursor est dentro del campo
Ejemplo: onKeyDown El evento se dispara al pulsar una tecla cuando el cursor est dentro del campo
Ejemplo: onKeyPress (leyendo el valor de la tecla pulsada) El evento se dispara al mantener pulsada una tecla cuando el cursor est dentro del campo y el alert muestra el resultado de ejecutar una funcin javascript que captura el valor de la tecla pulsada. Esa funcion tiene la forma siguiente:
if(window.event){ //cosas de IE var numero_de_tecla_pulsada = e.keyCode //recoge en IE el valor ASCII de la tecla } else if(e.which){ // Cosas Netscape/Firefox/Opera var numero_de_tecla_pulsada = e.which //recoge valor ASCII en otros navegadores } /* obtiene el caracter correspondiente al codigo ASCII recogido */ caracter_de_la_tecla_pulsada = String.fromCharCode(numero_de_tecla_pulsada); /* devuelve el valor del caracter correpondiente a la tecla pulsada */ return caracter_de_la_tecla_pulsada; } </script>
El botn submit
No presenta mayores complicaciones. Es un input type button (tambin podra ser una imagen que lleva asociado el evento onClick que lleva implcita la funcin submit() (enviar) el formulario que se indica.
Haz clic Haz doble clic Quita el ratn Pulsa cualquier botn Suelta cualquier boton
Cambios en los contenidos de una pgina Cambios de contenido de los elementos de una pgina
Los contenidos de los elementos de una pgina web (vistos como objetos JavaScript) son recogidos como valores en una de sus propiedades. El problema es que dependiendo del tipo objeto la propiedad ser distina y por tanto habr que tomar en consideracin este aspecto. A modo de ejemplo, para conocer el contenido de un elemento del tipo div tendramos que utilizar la propiedad innerHTML de modo que: document.getElementById('identificador_del_div').innerHTML contendra el valor de ese elemento. Igual que hacamos en con las propiedades de los objetos en PHP la lectura de ese valor podra hacerse por medio de: document.getElementById('identificador_del_div').innerHTML=nuevo_contenido
Ver ejemplo Ver cdigo fuente
Intentaremos incluir en las lneas siguientes una lista de los diferentes elementos de una pgina y de las propiedades que permiten modificar sus contenidos. Objetos con las etiquetas: <div>, <p>, <td>, <ul>, <li>, <tr>*, <table>* (Las sealadas con * parecen no funcionar en Internet
Explorer)
La lectura y/o modificacin de los contenidos de los objetos de estos tipos puede hacerse por medio de la propiedadinnerHTML. Si un objeto contiene otros objetos el valor de la propiedad innerHTML incluir a estos. Puedes verlo en este ejemplo.
Ver ejemplo Ver cdigo fuente
Para esas lecturas y/o modificaciones pueden utilizarse funciones similares a estas:
<script type="text/javascript"> function lee (identificador){ alert(document.getElementById(identificador).innerHTML); } function cambia (identificador,nuevo_valor){ document.getElementById(identificador).innerHTML=nuevo_valor; alert(document.getElementById(identificador).innerHTML); } </script>
Aqu puedes ver un ejemplo de utilizacin en los diferentes elementos.
Ver ejemplo Ver cdigo fuente
Objetos con las etiquetas: <img> o <iframe>(Las sealadas con * parecen no funcionar en Internet Explorer) La lectura y/o modificacin de los contenidos de los objetos de estos tipos puede hacerse por medio de la propiedad src. Puedes verlo en este ejemplo.
Ver ejemplo Ver cdigo fuente
Para esas lecturas y/o modificaciones pueden utilizarse funciones similares a las contempladas en el prrafo anterior. Una ligera modificacin en su estructura, introduciendo un nuevo parmetro (tipo) y un operador condicional podr permitirnos utilizar la misma funcin en ambas modalidades:
<script type="text/javascript"> function lee (identificador,tipo){ if(tipo=='imagen' || tipo=='iframe'){//condicion particular alert(document.getElementById(identificador).src); }else if(tipo=='' || tipo==null){// condicion general alert(document.getElementById(identificador).innerHTML); } } function cambia (identificador,nuevo_valor,tipo){ if(tipo=='imagen' || tipo=='iframe'){// condicion particular document.getElementById(identificador).src=nuevo_valor; alert(document.getElementById(identificador).src); }else if(tipo=='' || tipo==null){// condicion general document.getElementById(identificador).innerHTML=nuevo_valor; alert(document.getElementById(identificador).innerHTML); } } </script>
Aqu puedes ver un ejemplo de utilizacin de estas nuevas funciones con los diferentes elementos.
Ver ejemplo Ver cdigo fuente
Objetos con la etiqueta: <object> que permite incluir como tal: imgenes, vdeos, sonidos o, de forma similar a iframe, pginas web.
El uso de objetos parece que va ser la opcin de futuro. Sin embargo no es fcil superar los obstculos que actualmente se plantean cuando se trata de utilizar cdigo compatible entre los navegadores ms usados. Parafraseando a don Quijote diremos aquello de Con la iglesia hemos dado, Sancho aunque este caso no se trate de los muros de la parroquial de El Toboso sino con las diferentes maneras de interpretar los objetos por parte de los distintos navegadores. Intentaremos analizar cada uno de los tipos (tipos MIME) de contenidos de los objetos. Imgenes Este tipo de objetos se incluyen en los documentos mediante la sintaxis: <object data="ruta y nombre del fichero" class="(opcional)" style="(opcional)" id="(opcional)"></object> Como podrs observar el nico atributo de la etiqueta object que tiene condicin de imprescindible es data. Loa restantes class, style (hacen alusin a los estilos aplicables) e id son opcionales aunque para los fines aqu propuestos (modificacin de contenidos) el atributo id es imprescindible. El caso de las imgenes es el que ofrece mayor compatibilidad entre navegadores. Para leer datos de la imagen actual bastara con leer la propiedad data. Para modificarlos sera suficiente modificar el valor de esa propiedad tal como puedes ver en este ejemplo. Como podrs observar no hemos incluido el tipo MIME ya que, al parecer, los navegadores habituales (Firefox, Opera, Chrome, IE y Safari) son capaces de gestionar imgenes en los formatos ms frecuentes (jpg, png, gif) sin necesidad de especificar su tipo MIME concreto.
Ver ejemplo
Vdeos La proliferacin de formatos de vdeo y las especificaciones poco estandarizadas de los navegadores hacen que la gestin de este tipo de archivo resulte un autntico rompecabezas. Ante esta situacin hemos optado por la calle del medio que no es otra cosa que tratar de insertar los vdeos en un formato nico (el de extensin .swf por ser uno de los ms populares) y sugerir la transformacin del formato cuando nuestros originales procedan de fuentes en otro formato. Existen aplicaciones gratuitas que permiten efectuar ese tipo de transformaciones sin dificultad alguna. Considerando ese formato la inclusin de un fichero de vdeo requerira el uso de una sintaxis como esta: <object data="nombre del video" type="application/x-shockwave-flash" width="ancho" height="alto" id="(opc)"> <param name="movie" value="nombre del video" /> <param name="quality" value="best" /> <param name="bgcolor" value="#cccccc" /> <param name="scale" value="noScale" /> <param name="play" value="false" /> <param name="loop" value="0" /> </object> Los valores marcados en rojo son obligatorios y los incluidos en cursiva opcionales. Podrs observar una informacin aparentemente redundante. El nombre del vdeo se incluye como valor de parmetro movie (por compatibilidad con Internet Explorer) y como data (por compatibilidad con los restantes navegadores habituales). Los parmetros play pueden establecer con un valor booleano (cuando se configura como true la reproduccin de vdeo comenzar inmediatamente despus de cargarse la pgina, si se hace false ser necesario que el usuario la active de forma manual). Cuando se trata de loop si se le asigna el valor false la reproduccin se detendr en el momento en que se haya llegado al final del mismo. Si se configura como true al llegar al final de vdeo empezar una nueva reproduccin del mismo. En cuanto al parmetro scale admite como valores: default (permite visualizar sin distorsin el vdeo completo ajustndolo a las dimensiones especificadas en el style del mismo. Las zonas no ocupadas por la imagen aparecern del color especificado en el parmetro bgcolor), noborder (ajusta el tamao del vdeo para que ocupe todo el rea especificada sin distorsionar la imagen. Para evitar la distorsin recortara la imagen si fuera preciso),exactfit (rellena todo el res especificada distorsionando la imagen si fuera necesario) o noscale (impide la ampliacin de la imagen para ajustarse al area especificada. ) El parmetro quality admite como valores: low (antepone la velocidad de reproduccin al aspecto y nunca suaviza las imgenes), autolow (prioriza la velocidad de reproduccin pero intenta mejorar el aspecto y suavizar las imgenes siempre que las caractersticas del hardware lo permitan), autohigh (establece igual prioridad inicial a velocidad y calidad. Si la visualizacin se ralentiza mejora la velocidad de reproduccin sacrificando el suavizado de la imagen), medium (es una calidad intermedia entre la baja -Low- y la alta -high-), high (prioriza el aspecto a la velocidad de reproduccin) o best (proporciona la mejor calidad de visualizacin sin tener en cuenta la velocidad de reproduccin). Las modificaciones, cuando se trata de compatibilizar navegadores, s que abren una ventana a la demencia. Cuando se trata de modificar los parmetros width heigth no surge ningn problema aparente. Basta con
utilizardocument.getElementById('identificador').setAttribute('width', nuevo valor). Si intentamos, mediante el mismo procedimiento modificar otros parmetros veremos que esa opcin solo funciona en Internet Explorer. Pero, sin duda, lo ms esperpntico es cambiar el vdeo que se visualiza. Ah si que hay una modalidad para cada una de las opciones. Cuando se trata de Internet Explorer se logra mediante:document.getElementById(identificador).movie=nuevo_valor y cuando una piensa que para otros navegadores la solucin podra ser del tipo document.getElementById(identificador).data=nuevo_valor la ilusin se desvanece cuando uno intenta probar esa opcin en Chrome. All no funciona. Una solucin (ms bien debera decir una chapuza) puede ser esta: Incluimos el objeto dentro de una div Cuando el navegador sea Internet Explores modificamos el parmetro movie del objeto flash Cuando el navegador no sea Internet Explorer reescribimos la totalidad del contenido del contenedor divmodificando en ese proceso el valor del parmetro data. Una de las mltiples formas (seguro que no la ms eficiente) podra ser la utilizacin de una funcin JavaScript similar a esta:
/* la funcion recibe cinco parmetros: contenedor: Recogera el nombre de la div creada para contener el objeto vdeo. identificador: es el identificador del objeto video tipo: es un parmetro para diferenciar distintos tipos de objetos atributo: recoge el nombre del atributo a modificar (data en este caso) nuevo_valor: ser el nombre, extensin y ruta del nuevo video */ function cambia_video (contenedor,identificador,tipo,atributo,nuevo_valor){ if(tipo=='flash'){ /* Comprobado que el tipo es flash, comprobamos la propiedad appName del objeto navigator si su valor es Microsoft Internet Explorer ser suficiente modificar el valor del parmetro movie. */ if(navigator.appName=="Microsoft Internet Explorer"){ document.getElementById(identificador).movie=nuevo_valor; }else{ /* Para navegadores diferentes a IE podemos unificar le proceso leyendo el contenido de la div contenedora del objeto y recogiendo su contenido en una variable que aqu llamamos anterior */ var anterior=document.getElementById(contenedor).innerHTML; /* Lo que debemos cambiar es el valor del atributo data (lo hemos recogido del parmetro atributo) asignndole por medio del signo = el nuevo valor que incluimos entre comillas. */ nuevo_valor=atributo+"=\""+nuevo_valor+"\""; /* Tenemos que sustitur el data anterior por el nuevo_valor. Creamos un nuevo objeto (new RegExp) expresin regular que estar formada por el atributo (data en nuestro caso) seguido de un signo igual. Detrs estar el el nombre actual (na serie de caracteres que identificaremos por medio de los metacaracteres (.*) y acabados en unas comillas. Invertimos la codicia (para delimitar en las primeras comillas que encuentre) por medio del metacaracter ? que sigue al * Como segundo parmetro incluimos el modificador "i" que hace la expresin insensible a maysculas/minsculas*/ valor_a_reemplazar=new RegExp(atributo+'=.*?"',"i"); /* aplicamos el mtodo replace a la cadena que contiene los datos actuales pasndole dos parmetros: valor a reemplazar y nuevo valor. El resultado ser la cadena ya actualizada */ var renovado=anterior.replace(valor_a_reemplazar,nuevo_valor); /* ya podemos modificar el elemento contenor insertndole sus nuevos valores */ document.getElementById(contenedor).innerHTML=renovado; }
} }
No podemos olvidarnos de que los vdeos incluidos por este procedimiento no disponen de elementos de control. Afortunadamente la gestin de esos controles es compatible con los diferentes navegadores por lo cual bastara con ejecutar alguno de estoy mtodos: objeto_flash.Play() (iniciara la reproduccin del vdeo),objeto_flash.Stop()(detendra la reproduccin) y objeto_flash.Rewind() (rebobinara el vdeo y lo devolvera a la posicin inicial) Considerando todas estas variables podramos llegar a algo como lo que puedes ver en este ejemplo.
Ver ejemplo Ver cdigo fuente
Pginas web La inclusin de pginas web en en objetos no presenta grandes complicaciones sintcticas. Sera suficiente una sintaxis similar a esta: <object type="text/html" data="direccion" width="250" height="250" id="identificador"> </object> Ahora el tipo MIME sera text/html (adecuado a su contenido) y el parmetro data nos permitira especificar la direccin URL. Parecera que la modificacin de los contenidos pasara por la modificacin del parmetro data. Y es cierto, solo que a medias. Hay navegadores que no responden a esa modificacin y la solucin (al menos una de las soluciones, seguramente ni la nica ni la mejor) es hacer algo similar a lo comentado para el caso del vdeo. Incluyendo el objeto dentro de una div contenedora y reescribiendo el contenido de esa div parece ser que se logra la ansiada compatibilidad entre navegadores. La funcin que permitiera el cambio de contenidos podra ser el resultado de una modificacin de la comentada anteriormente. Ahora puede aplicarse un procedimiento nico razn por la cual ya no es preciso diferenciar por nombre del navegador.
function cambia (contenedor,identificador,tipo,atributo,nuevo_valor){ if(tipo=='flash'){ if(navigator.appName=="Microsoft Internet Explorer"){ document.getElementById(identificador).movie=nuevo_valor }else{ var anterior=document.getElementById(contenedor).innerHTML; nuevo_valor=atributo+"=\""+nuevo_valor+"\""; valor_a_reemplazar=new RegExp(atributo+'=.*?"',"i"); var renovado=anterior.replace(valor_a_reemplazar,nuevo_valor); document.getElementById(contenedor).innerHTML=renovado; } } if(tipo=='web'){ var anterior=document.getElementById(contenedor).innerHTML; nuevo_valor=atributo+"=\""+nuevo_valor+"\""; valor_a_reemplazar=new RegExp(atributo+'=.*?"',"i"); var renovado=anterior.replace(valor_a_reemplazar,nuevo_valor); document.getElementById(contenedor).innerHTML=renovado; } }
Ver ejemplo Ver cdigo fuente
Ficheros de sonido mp3 La inclusin y reproduccin de ficheros de sonido en una web vuelve a abrir todo un mundo de opciones y tambin de incompatibilidades. Por una parte los formatos y por otra las extensiones (plug-in) multimedia del navegador que va a mostrar los paneles de control en la pgina web. La solucin chapuza (no es la ms elegante pero probablemente nos retrasar un poco la demencia) podra ser la unificacin. Podramos pensar en unificar el formato de los ficheros de sonido. Existen aplicaciones gratuitas tales como pazera o Audacity que permiten la edicin y el cambio de formato de audio. No hemos inclinado por unificar en formato mp3. El siguiente punto de unificacin habr de ser el plug-in reproductor. En este aspecto una opcin que nos parece razonable y prctica es la desarrollada en flash por alsacreations.fr bajo licencia Creative Commons y que, tal como puede verse en su pgina principal, ofrecen varias opciones de paneles de control para el reproductor mp3. La utilizacin de esta opcin requiere obtener el fichero dewplayer.zip y descomprimirlo en alguna parte del servidor. Ese archivo contiene una serie de ficheros con extensin .swf (son los distintos reproductores) e incluso unas instrucciones de uso.
La utilizacin de este tipo de objetos requiere una sintaxis como esta: <object type="application/x-shockwave-flash" data="(ver comentario)" width="ancho" height="alto" id="ident"> <param name="movie" value="(ver comentario)" /> </object> La compatibilidad famosa nos obliga a incluir, junto con el tipo MIME especfico de los ficheros flash, el parmetromovie con un value idntico al requerido por data. Adems de eso deberemos indicar el ancho y alto de visualizacin de plugin .swf (las dimensiones para las diferentes opciones puedes verlas en su pgina web). Los parmetros data y movie requieren particular atencin. Estn formados por: la ruta nombre y extension de fichero .swf que vayamos a utilizar como reproductor, seguida de ?mp3= y de la ruta, nombre y extensin de fichero mp3 que se pretende reproducir. Resultara una expresin del tipo: /reproductores/dewplayer.swf?mp3=/sonidos/mi_sonido.mp3 El cambio de fichero a reproducir requerira modificar el valor de movie en el caso de Internet Explorer o data en los restantes navegadores. Por lo que hemos podido comprobar, en este caso no es necesario recurrir a la inclusin del objeto en una div contenedora. Basta con asignar nuevo valor al parmetro data. Aqu tienes un ejemplo.
Ver ejemplo Ver cdigo fuente
La nica excepcin a esta obligatoriedad son los elementos de opcin (los input type="radio") que como puedes rescordar aqu utilizan ese name comn para formar agrupaciones. Adems del name podramos incluir en cada uno de los elementos un identificador nico utilizando el archimencionado atributoname. Aunque son perfectamente compatibles ambos atributos no resulta imprescindible,para nuestros propsitos, el uso de id. En cualquier caso, supongamos que disponemos de ambos atributos en una sintaxis tal como esta: <input type="text" name="obligatorio" id="identificador_unico" /> <input type="password" id="identificador_unico"name="obligatorio" /> <textarea id="identificador_unico"name="obligatorio" /></textarea> <select name="obligatorio" id="identificador_unico"/> <option id="identificador_unico">aaa</option>/>
<option id="identificador_unico">bbb</option> </select> <input type="radio" name="obligatorio" id="identificador_unico"/> <input type="checkbox" name="obligatorio" id="identificador_unico"/> Como vers hemos puesto indentificadore (nicos) en todo, incluso en lo sealado como option. Para aludir a los elementos podemoas hacerlo ahora mediante el ya comentado: document.getElementById('nombre del identificador') y podremos hacerlo por medio de una de estas otras dos opciones: document.getElementsByName('nombre').item(0) o document.getElementsByName('nombre')[0] El mtodo getElementById devuelve siempre un objeto nico. Por el contrario, el mtodo getElementsByName devuelvesiempre un array (incluso en los casos en lo que el array contenga un nico elemento). Por esa razn es necesario ser ms explcito e indicar a cual de los elementos del array nos referimos. Eso puede hacerse por medio del ndice del array especificado como [indice] o mediante .item(indice). En este segundo supuesto se utiliza siempre el punto seguido de la palabra item y, entre parntesis, el ndice del array. Como es lgico en los casos en los que el array contenga un solo elemento el ndice ser cero.
Cuidado! Ten cuidado con la sintaxis. En un caso se usa getElementById y en el otro getElementsByName. No siempre prestamos a la s toda la atencin que requiere.
Qu y cmo modificar?
Input type text, password y textarea Este tipo de elementos de los formularios permiten establecer y/o modificar los siguientes atributos: disabled Este atributo puede asignarse incluyendo el atributo disabled="disabled" en la etiqueta <text> o en cualquier otra que defina un elemento. Puede activarse o desactivarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').disabled=true; document.getElementById('identificador').disabled=false; document.getElementsByName('nombre')[0].disabled=true; document.getElementsByName('nombre')[0].disabled=false; document.getElementsByName('nombre').item(0).disabled=true; document.getElementsByName('nombre')item(0).disabled=false; Cuando est activado impide la modificacin de los contenidos de esos campos del formulario y, adems, sus valores no son enviados junto con el formulario. La variable identificada por el name de su formulario no ser recibida por el servidor. readOnly (cuidado con la sintaxis, JavaScript diferencia maysculas de minsculas) Este atributo puede asignarse incluyendo el atributo readonly="readonly" en la etiqueta <text> o en cualquier otra que defina un elemento. Puede activarse o desactivarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').readOnly=true; document.getElementById('identificador').readOnly=false; document.getElementsByName('nombre')[0].readOnly=true; document.getElementsByName('nombre')[0].readOnly=false; document.getElementsByName('nombre').item(0).readOnly=true; document.getElementsByName('nombre')item(0).readOnly=false; Cuando est activado tambin impide la modificacin de los contenidos de esos campos del formulario pero, a diferencia de disabled permite el envo de los valores que contenga incluso cuando ese valor sea una cadena vaca.
value Este atributo puede asignarse incluyendo el atributo value="valor preasignado" en la etiqueta <text> o en cualquier otra que defina un elemento. Puede modificarsr por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').value='nuevo valor'; document.getElementsByName('nombre')[0].value='nuevo valor'; document.getElementsByName('nombre').item(0).value='nuevo valor';
Ver ejemplo Ver cdigo fuente
Input type select Tambin admite, y con las mismas consecuencias, la utilizacin de disabled. Adems tiene una peculiaridad importante. Las diferentes posibilidades de eleccin se incluyen en el formulario dentro de etiquetas <option></option> Para referirnos desde JavaScript a una opcin concreta tenemos varias posibilidades: document.getElementById('identificador_del_select').options[indice] La etiqueta select debe llevar un id. Las options constituyen un array escalar cuyos ndices (empiezan en cero) y que mantiene el mismo orden en que se van insertando las option. La prima tendr ndice cero, la segunda uno, etctera. document.getElementsByName('name_del_selector')[0].options[indice] En este supuesto identificamos el select por su name. Tal como hemos comentado anteriormente el resultado se representa mediante un array del que extraemos el primer elemento [0] (suponemos un solo select con ese nombre, de ah el cero). Con este paso tenemos completada la primera parte de la eleccin. Hay que aadirle a cual de las opciones hacemos referencia y para ello usamos options[indice] igual que en el caso anterior. document.getElementById('identificador_especifico_de_la opcion') Este ltimo supuesto requiere que dentro de la etiqueta <option> se haya incluido un id para asignarle un identificador nico En el elemento elegido es factible seleccionar uno de estos atributos: value Por medio de esta propiedad y con una de estas sintaxis document.getElementById('identificador').options[indice].value='nuevo valor'; document.getElementsByName('nombre_del_select')[0].options[indice].value='nuevo valor'; document.getElementsByName('identificador_de_la_opcion').value='nuevo valor'; se permite modificar el valor de una opcin. El cambio no afecta a la leyenda visualizada en pantalla pero s modifica el contenido transferido al servidor. Recuerda que la leyenda es considerada nicamente valor por defecto cuando no se asigna ningn value dentro de la etiqueta option text Por medio de esta propiedad y con una de estas sintaxis document.getElementById('identificador').options[indice].text='nuevo texto'; document.getElementsByName('nombre_del_select')[0].options[indice].text='nuevo texto'; document.getElementsByName('identificador_de_la_opcion').text='nuevo texto'; se permite modificar el texto de la leyenda de una opcin. El cambio no afecta al valor enviado al servidor salvo que no haya sido especificado el atributo value. Recuerda que el texto solo es tomado como value en el caso de que este no estuviera definido en la etiqueta option selected La seleccin de una de las opciones puede hacerse bien de la forma tradicional (eligiendo con el ratn en el selector) o bien por medio de una sentencia javaScript independiente del selector. Mediante una de estas sintaxis: document.getElementById('identificador').options[indice].selected=true; document.getElementsByName('nombre_del_select')[0].options[indice].selected=true; document.getElementsByName('identificador_de_la_opcion').selected=true; podremos seleccionar la opcin correspondiente. Al seleccionar una de las opciones se deseleccionaran las dems. remove Por medio de este mtodo puede eliminarse items de una lista de opciones. La sintaxis sera document.getElementById('identificador').remove(indice); document.getElementsByName('nombre_del_select')[0].remove(indice);
dnde ndice es el nmero de orden (contado a partir de cero) de la posicin que ocupa dentro del select la opcin que pretendemos eliminar. add La seleccin de una de las opciones puede hacerse bien de la forma tradicional (eligiendo con el ratn en el selector) o bien por medio de una sentencia javaScript independiente del selector. Mediante una de estas sintaxis: document.getElementById('identificador').options[indice].selected=true; document.getElementsByName('nombre_del_select')[0]options[indice].selected=true; document.getElementsByName('identificador_de_la_opcion').selected=true; podremos seleccionar la opcin correspondiente. Al seleccionar una de las opciones se deseleccionaran las dems.
Ver ejemplo Ver cdigo fuente
Input type select multiple Mantiene los mismos mtodos y propiedades ya comentado para el select simple. Solamente hay que tener en cuenta que se diferencia de aquel en que dentro de la etiqueta &select> incluye ahora los atributos:multiple="multiple" (para establecer la condicin de multiple) size="numero" (para establecer el nmero de items que se visualizarn de forma simultnea). Adems, hay que tomar en consideracin algo de suma importancia. El atributo name ha de estar asociado con un array para permitir la transferencia de los mltiples valores eventualmente elegidos. La forma adecuada de hacerlo sera similar a: value="nombre_de_variable[ ]" Respecto a lo comentado para el input simple la nica diferencia sera evitar el uso de la sintaxis que utilice el nombre_de_variable asignado en value. Es decir, no usar document.getElementsByName('nombre_del_select')comentada para el select simple.
Ver ejemplo Ver cdigo fuente
Input type radio Los botones de opcin tiene la peculiaridad de agruparse automticamente sin ms que asignarles el mismo valor al atributo name. De esa forma, cuando se selecciona una de las opciones se deseleccionan de forma automtica todas las dems siempre que compartan su mismo name. Este tipo de elementos de los formularios permiten establecer y/o modificar los siguientes atributos: disabled Este atributo puede incluirse en la etiqueta <input type="radio"> escribiendo disabled="disabled". Puede activarse o desactivarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').disabled=true; document.getElementById('identificador').disabled=false; document.getElementsByName('nombre')[indice].disabled=true; document.getElementsByName('nombre')[indice].disabled=false; Se usaran las dos primeras opciones cuando se haya establecido un id="identificador" como atributo de la etiqueta <input type="radio">. En caso de que no exista ese id podemos hacer uso de las dos ltimas opciones. En ellas nombre se refiere al valor comn asignado a name siendo el valor de indice en[indice] el nmero de orden (empezando por cero) dentro del grupo de la opcin. Como siempre ese nmero de orden atiende a aquel en el que han sido creados los diferentes elementos del grupo. value Este atributo suele incluirse en la etiqueta <input type="radio"> escribiendo value="valor". Puede crearse o modificarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').value="valor_asignado"; document.getElementsByName('nombre')[indice].value="valor_asignado"; checked Este atributo (indica que la opcin est seleccionada por defecto) suele incluirse en la etiqueta <input type="radio"> escribiendo checked="checked". Puede crearse o modificarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').checked=true; document.getElementById('identificador').checked=false; document.getElementsByName('nombre')[indice].checked=true; document.getElementsByName('nombre')[indice].checked=false;
Cuando se selecciona una de las opciones (por medio del ratn o a travs de una sentencia JavaScript) se deselecciona de forma automtica cualquier otra que estuviera previamente seleccionada. name Este atributo ya reseado anteriormente puede crearse modificarse por medio de JavaScript utilizando una de las sintaxis siguientes: document.getElementById('identificador').name='nuevo_nombre'; document.getElementsByName('nombre')[indice].name='nuevo_nombre';
Cuidado! Cuando se cambia el nombre el elemento deja de pertenecer al grupo. Por esa razn sera perfectamente factible seleccionarlo sin que se deseleccionen susantiguos compaeros de grupo.
agregar una nueva opcin Agregar una nueva opcin a un grupo requiere incluirla en el lugar adecuado (al lado de las opciones que comparten grupo) y asignarle un texto identificativo. Una de las opciones para poder llevar a cabo esa inclusin sera tomar la cautela de crear un contenedor (un elemento tipo div con un id a que llamaremos aqu contenedor aunque pueda tener cualquier nombre). El proceso de agregar una nueva opcin consistira en: Leer el contenido de la div que incluye las opciones. Puede hacerse por medio de innerHTML Agregar a la cadena innerHTML la informacin correspondiente al nuevo elemento Actualizar el contenido de la div contenedora. Esas modificaciones podran hacerse por medio de una funcin similara a esta:
function agrega_radio(contenedor,nombre,texto,valor,identificador) { /* leemos el contenido actual del contenedor y lo guardamos en la variable contenido */ var contenido=document.getElementById(contenedor).innerHTML; if (identificador==null || identificador==''){ /*agregamos los datos del nuevo input sin incluir id especifico */ contenido += "<input type='radio' name='"+nombre+"' "; contenido += "value='"+valor+"' />"+texto; }else{ /*agregamos los datos del nuevo input incluyendo un id */ contenido += "<input type='radio' name='"+nombre+"' "; contenido += "id='"+identificador+"' value='"+valor+"' />"+texto; } /* reemplazamos los valores incluidos en el contenedor */ document.getElementById(contenedor).innerHTML=contenido; }
Ver ejemplo Ver cdigo fuente
Input type checkbox Es conveniente tener bien presente que si dos elementos de distinto o igual tipo (con excepcin de radio) tienen asignado un mismo name el valor transferido por medio del formulario ser el ltimo de los incluidos con ese nombre comn. Puedes comprobarlo en este ejemplo.
Ver ejemplo Ver cdigo fuente
Es conveniente tener bien presente que los distintos elementos de este tipo han de tener (por la razn comentada en el prrafo anterior) nombres distintos. Dicho esto los mtodos y propiedades comentados para el caso del radio son aplicables en su mayora en este tipo de elementos. La identificacin de los elementos se hara ahora por medio de document.getElementById('identificador'); document.getElementsByName('nombre')[0] El valor cero asignado en la segunda de las opciones se justifica por el hecho de que para cada nombre slo existir un elemento de este tipo.
Ver ejemplo Ver cdigo fuente
Esta miscelnea de posibilidades tiene una limitacin importante. A la hora de efectuar modificaciones en los valores de los diferentes elementos ya que no dispone de medios para obtener esos nuevos valores desde el servidor. En la pgina siguiente intentaremos ver la utilidad y forma de utilizacin de AJAX para estos menesteres.
<html> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> <title>Objeto Ajax</title> <script type="text/javascript"> if(window.XMLHttpRequest) { objetoAjax = new XMLHttpRequest(); } else if(window.ActiveXObject) { objetoAjax = new ActiveXObject("Microsoft.XMLHTTP"); } alert(objetoAjax); </script> </head> <body> </body> </html>
Ver ejemplo
Igual que ocurra en PHP y tal como comentamos en la pgina anterior los objetos JavaScript disponen de mtodos a los que se alude con la sintaxis nombre_del_objeto.nombre_del_metodo(parametros). En el caso de los objetos de la clase XMLHttpRequest las mtodos ms usuales son los siguientes: objeto.getAllResponseHeaders() Devuelve todas las de cabeceras HTTP de la peticin como una cadena 0 En reposo. Sin comenzar una comunicacin con el servidor 1 Transaccin iniciada. Abierta la comunicacin 2 Transaccin en ejecucin. Cabeceras recibidas 3 Transaccin ejecutndose. Cargando datos 4 Transaccin con el servidor completada objeto.getResponseHeader('nombre_de_la_cabecera') Devuelve la cabecera HTTP cuyo nombre se incluye como parmetro. Algunos de esos nombres son: Server En reposo. Sin comenzar una comunicacin con el servidor Date Transaccin iniciada. Abierta la comunicacin Content-length Transaccin en ejecucin. Cabeceras recibidas Content-type Transaccin ejecutndose. Cargando datos Conection Transaccin en ejecucin. Cabeceras recibidas Keep-alive timeout:Es el tiempo en segundos que Apache esperar peticiones subsiguientes antes de cerrar una conexin persistente. Max: es el nmero de peticiones permitidas por conexin. objeto.open(metodo, URL, tipo, usuario, contrasea') Prepara una peticin de informacin al servidor, pero no la enva. Requiere los siguientes parmetros metodo Puede tomar los valores: GET, POST o PUT (este ltimo de uso mucho ms infrecuente) URL Es la direccin absoluta o relativa de la pgina solicitada al servidor. Como norma general, cuando se utiliza el mtodo GET se incluyen junto con URL las variables que deseen incluirse en la peticin. Es decir la ya conocida sintaxis: nombre_de_la_pagina.extension?variable1=valor1&variable2=valor2. Cuando se usa el mtodo POST no se agregan valores de las variables aqu. En ese caso se incluirn (en forma de cadenas del tipo "variable1=valor1&variable2=valor2") como parmetros datos en la llamada al mtodo sendque comentamos ms abajo tipo Admite como valores true o false. Un valor true indica que el proceso del script contina despus del mtodo send(), sin esperar a la respuesta, y false indica que el script se detiene hasta que se complete la operacin, tras lo cual se reanuda la ejecucin. usuario y contrasea Son parmetros opcionales para aquellos casos en que esos valores sean requeridos por el servidor. objeto.setRequestHeader(etiqueta, valor ) Permite establecer cabeceras personalizadas en la peticin HTTP. Cuando se utiliza el mtodo POST debe incluirse una llamada a este mtodo antes de invocar el mtodo send() incluyendo como parmetros etiqueta-valor los siguientes:"Content-Type", "application/x-www-form-urlencoded". Como podrs comprobar guarda una gran similitud con lo indicado para ENCTYPE cuando hablbamos del envo de formularios. objeto.send(datos) Enva la peticin al servidor. El parmetro datos debe incluirse obligatoriamente. Si no hay datos que deban enviarse se escribir null. Se entienden como datos de este parmetro cadenas del tipo: "usuario=pepe&password=pepa" similares a las ya mencionadas cuando hacamos alusin al mtodo GET cuanto tratbamos los formularios
Reacciona a cada cambio de estado modificacin de una propiedad, ejecucin de un mtodo, etctera del objeto ejecutando la funcin gran_hermano(). Dicho de otra forma, reacciona automticamente cada vez que algo cambia pudiendo hacerlo de forma distinta en cada situacin de acuerdo con lo especificado en la propia funcin gran_hermano() . En este ejemplo puedes ver (los resultados varan dependiendo del navegador que ests usando) la lista de propiedades de un objetoXMLHttpRequest. La visualizacin utiliza un bucle Javascript con la siguiente sintaxis: for (var=variable in nombre_del_objero){ //recorre el objeto pasando por cada una de sus propiedades document.write(variable+"<br>"); //escribimos el nombre de la propiedad concatenado con un salto de linea }
Ver ejemplo Ver cdigo fuente
/* la funcin recibe dos parmetros, la URL de la pgina que va a solicitarse al servidor (origen) y la div en la que van a escribirse los resultados */ function obtenerDatos(origen, dest){ /* comprueba que existe el objeto XMLHttpRequest */ if(objetoAjax) { /*recogemos el valor dest en la variable GLOBAL destino su condicin de global se debe a que no lleva delante la palabra reservada var. De esta forma (GLOBAL) destino estar disponible para cualquier funcion o parte del script */ destino=dest; /*preparamos la peticin mediante el open. Incluimos el parmetro GET y el la direccin de la URL que solicitaremos al servidor. No incluimos el parmetro tipo con lo cual tomar su valor por defecto que es true. */ objetoAjax.open("GET", origen); /* asignamos al evento cambio de estado la ejecucion de la funcion gran_hermano. Observa que no ponemos parntesis en la llamada. Elo se debe a que lo que pretendemos es asignar al evento la ejecucion de la funcin. Si incluyramos los parntesis tipicos gran_hermano() lo que estaramos tratando de asignar al evento no sera la ejecucin de la funcin sino el resultado de esta. */ objetoAjax.onreadystatechange = gran_hermano; /* preparada la peticion y activada la captura de eventos ya solo nos queda enviar la peticion al servidor */ objetoAjax.send(null); } //cerramos el if } //finalizamos la funcion /* esta funcion no recibe ningun parmetro pero tiene disponible el valor de
la variable destino creada (creada como GLOBAL) por la funcin anterior */ function gran_hermano(){ /* comprueba si la propiedad readyState vale 4 (Transaccion completada) y que la peticin haya sido considerada correcta por el servidor (status=200)*/ if (objetoAjax.readyState==4 && objetoAjax.status==200) { /* si se completo correctamente la transaccin escribe en la div de destino el texto recibido del servidor (responseText) */ document.getElementById(destino).innerHTML = objetoAjax.responseText; }else{ /* si no se complet la peticion le indicamos que escriba "procesando " */ document.getElementById(destino).innerHTML ="procesando.."; } }
Aqu tienes dos casos de utilizacin de esa funcin. Observa las diferencias de respuesta.
Ver ejemplo Ver cdigo fuente Ver ejemplo Ver cdigo fuente
Habrs podido observar que el segundo ejemplo presenta incorrectamente algunos carcteres. La explicacin es simple. En el primer caso al crear el fichero de texto lo hemos guardado con codificacin UTF8 que es la que lee correctamente. El segundo fichero, idntico al anterior, ha sido guardado con codificacin ANSI y ese el origen de los problemas de visualizacin de los carcteres con tilde, las ees, etctera. Existen otras soluciones alternativas a descrita anteriormente. En vez de la funcin gran_hermano incluimos una funcin annima tal como puedes ver en este cdigo fuente.
/* la funcin recibe dos parmetros, la URL de la pgina que va a solicitarse al servidor (origen) y la div en la que van a escribirse los resultados */ function obtenerDatos(origen, dest){ /* comprueba que existe el objeto XMLHttpRequest */ if(objetoAjax) { /*recogemos el valor dest en la variable GLOBAL destino su condicin de global se debe a que no lleva delante la palabra reservada var. De esta forma (GLOBAL) destino estar disponible para cualquier funcion o parte del script */ destino=dest; /*preparamos la peticin mediante el open. Incluimos el parmetro GET y el la direccin de la URL que solicitaremos al servidor. No incluimos el parmetro tipo con lo cual tomar su valor por defecto que es true. */ objetoAjax.open("GET", origen); /* asignamos al evento cambio de estado la ejecucion de la funcion anmina que definimos con la palabra function() ahora con parntesis ya que esa es exigencia para su definicin*/ objetoAjax.onreadystatechange = function(){ /* comprueba si la propiedad readyState vale 4 (Transaccion completada) y que la peticin haya sido considerada correcta por el servidor (status=200)*/ if (objetoAjax.readyState==4 && objetoAjax.status==200) { /* si se completo correctamente la transaccin escribe en la div de destino el texto recibido del servidor (responseText) */ document.getElementById(dest).innerHTML = objetoAjax.responseText; }else{ /* si no se complet la peticion le indicamos que escriba "procesando " */ document.getElementById(dest).innerHTML ="procesando.."; } } /* preparada la peticion y activada la captura de eventos ya solo nos queda enviar la peticion al servidor */
Mediante POST En este otro ejemplo utilizaremos POST. En esta ocasin pondremos como valor del parmetro URL del mtodo opennicamente multiplica.php Incluimos objetoAjax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") antes de invocar el mtodosend Ahora deberemos incluir los datos. objetoAjax.send("a=13&b=48$c=Hola").
Ver ejemplo Ver cdigo fuente Ver cdigo fuente del script
Cuidado! Observa las diferencias entre los resultados de ambos ejemplos. Cuando se usa GET la correcta visualizacin de los resultados en el script php (en este caso multiplica.php) requerira tratar la cadena de texto por medio de la funcin PHP utf8_decode. No olvides que esta funcin, junto con utf8_encode pueden resultar muy tiles en muchas ocasiones.
de texto). Este evento activa un funcin (en este caso alert, ms adelante hemos de cambiarla y sustituirla por el nombre de una funcin) y adems, por medio del parmetro this.value estamos recogiendo el valor actual de ese campo. 3. Necesitamos disponer y visualizar todos los valores posibles que contengan los carcteres tecleados. Para visualizarlos necesitaremos agregar un elemento a la pgina, por ejemplo una <div id="pruebas"> que ser la encargada de visualizar los resultados. Supongamos que disponemos de los datos en una tabla MySQL llamada paises, que contiene un campo llamado pais en el que se incluyen los nombres de los paises del mundo . Necesitamos un script PHP que consulte esa tabla cada vez que modificamos el input (tecleando o borrando) y que esa consulta considere coincidencias todos los registros que contengan la cadena escrita en el input. . Entre las muchas opciones posibles cabra efectuar esa consulta utilizando una clasula WHERE Nombres LIKE '%$busca%' (bucara el contenido de la variable $busca en cualquier posicin del nombre del pas) o por medio de WHERE Nombres LIKE '$busca%' buscara unicamente la coincidencia al comienzo del nombre. Este podra ser el script de una consulta de este tipo:
Ver ejemplo Ver cdigo fuente
4. Una vez disponemos del script que realiza la consulta MySQL ya solo necesitamos hacer algunas modificaciones en la pgina que el objeto XMLHttpRequest Modificar la funcin invocada por el evento onKeyUp en el campo input escribiendo algo como: <input type="text" id="entrada" name="miprueba" value="" onKeyUp="obtenerDatos('ejemplo779.php?busca='+this.value,,'pruebas');" /> De esta forma cada vez que se pulsara una tecla se ejecutaria la funcin obtenerDatos pasando dos parmetros: la cadena formada por ejemplo779.php?busca= (nombre del script que ejecuta la bsqueda seguido del nombre de la variable utilizada para aquella bsqueda y del signo igual) concatenada con el valor actual del campo de texto this.value El segundo paramtro es identificador del div al que hemos llamado pruebas y que ser el lugar dnde aparecern los resultados. Tenemos que definir la funcin JavaScript obtenerDatos() que puede tener una sintaxis como esta:
function obtenerDatos(origen, destino){ if(objetoAjax) { /* la variable origen incluye en este caso la cadena de busqueda*/ objetoAjax.open("GET",origen); objetoAjax.onreadystatechange = function(){ if (objetoAjax.readyState==4 && objetoAjax.status==200){ /* el estilo de la div destino tiene asignado display=none, eso significa que ahora que va a tener datos hay que cambiar es estilo a block para que pueda visualizarse */ window.document.getElementById(destino).style.display='block'; /* se visualiza la lista utilizando el estilo que asignado a ese elemento en el script de bsqueda. Los resultados resultantes de la consulta aluden a una funcion llamada selecciona que aun no ha sido definida */ window.document.getElementById(destino).innerHTML=objetoAjax.responseText; } } objetoAjax.send(null); } }
An tendramos pendiente definir la funcin selecciona() que hemos asociado al evento onClick para cada uno de los elementos de la lista resultante de la bsqueda. El objetivo de esa funcin sera que al hacer clic se rellenara el campo de texto del formulario con el valor incluido en ella como parmetro y que dejara de visualizarse la capa que contiene la lista de elementos. Para lograr esos fines bastara con que fuera similar a esta:
Ver ejemplo
El uso de la opcin POST requerira una pequea modificacin de la funcion javascript obtenerDatos() que podra quedar ahora de la forma siguiente:
function obtenerDatos(valor, origen, destino){ if(objetoAjax) { /* formamos una cadena de consulta con la palabra busca, nombre de la variable y el valor capturado de input text. Esa cadena ser incluida como parmetro al invocar el metodo send */ cadena_de_busqueda="busca="+valor; /* la variable origen incluye en este caso unicamente el nombre del script*/ objetoAjax.open("POST",origen); objetoAjax.onreadystatechange = function(){ if (objetoAjax.readyState==4 && objetoAjax.status==200){ /* el estilo de la div destino tiene asignado display=none, eso significa que ahora que va a tener datos hay que cambiar es estilo a block para que pueda visualizarse */ window.document.getElementById(destino).style.display='block'; /* se visualiza la lista utilizando el estilo que asignado a ese elemento en el script de bsqueda. Los resultados resultantes de la consulta aluden a una funcion llamada selecciona que aun no ha sido definida */ window.document.getElementById(destino).innerHTML=objetoAjax.responseText; } } /* el uso de POST nos obliga a llamar a este mtodo incluyendo sus encabezado */ objetoAjax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") /* la cadena_de_busqueda se incluye ahora como parmetro del mtodo POST */ objetoAjax.send(cadena_de_busqueda); } }
Ver ejemplo Ver cdigo fuente
dnde nombre_del_objeto, ser el nombre del nuevo objeto y {} la sintaxis obligatoria para la creacin de un nuevo objeto por el momento vaco usando la notacin JSON. Otra de las opciones ms simples es la utilizacin de la sintaxis: nombre_del_objeto =new Object() dnde nombre_del_objeto ser, igual que en el caso anterior, el nombre del nuevo objeto y new Object() la sintaxis obligatoria (recuerda que JavaScript diferencia entre letras maysculas y minsculas) para la creacin de nuevo objeto. Como podrs observar, el nuevo objeto carece de propiedades y/o mtodos. Por el momento es una especie de objeto vaco. Tambin es posible la creacin de objetos por medio de una funcin constructora que, de forma similar a las clases de PHP, nos permite, al ser invocada, la creacin y la asignacin de propiedades y sus valores a un nuevo objeto. En ese caso son necesarios dos elementos: la funcin constructora y la llamada a esa funcin. El primero de los elementos tendra una estructura de este tipo: function funcion_constructora(parametro1, parametro2,...) { this.propiedad1 = parametro1 this.propiedad1 = parametro1 .... } La palabra reservada this tiene una significacin idntica a la comentada para $this en PHP. De forma muy similar a lo que ocurra en aquel caso. De igual modo this.propiedad se comportara en JavaScript de forma similar a $this->propiedad en PHP. En ambos casos aludira a la propiedad en el objeto actual. La creacin de objetos utilizando una funcin constructora requerira algo como esto: nombre_del_objeto = new funcion_constructora (parametro1, parametro2,... ) ahora la palabra reservada new va seguida del nombre de la funcin constructora y de los parntesis que pueden incluir los eventuales parmetros requeridos por la funcin. Esta forma de creacin de objetos permite una variante. Es la siguiente: variable = function funcion_constructora(parametro1, parametro2,...) { this.propiedad1 = parametro1 this.propiedad1 = parametro1 .... } que slo difiere de la anterior en el hecho de que hemos incluido la funcin constructora como valor de una variable. Ahora para la creacin del nuevo objeto debemos invocar el nombre de la variable con una sintaxis similar a esta: nombre_del_objeto = new variable (parametro1, parametro2,... ) No acaban aqu las posibilidades de creacin de objetos JavaScript. Los objetos con notacin JSON pueden ser creados a partir de una cadena de texto. Esa posibilidad tiene particular inters ya que nos va a permitir crear objetos JavaScript a partir de cadenas recibidas por medio de una peticin a un servidor. Es decir, se abre la posibilidad de intercomunicar objetos JavaScript con PHP y tambin objetos PHP con JavaScript. Por el momento conformmosnos con conocer el procedimiento de creacin de esos objetos JavaScript. Por medio de la funcin eval podemos convertir una cadena de carcteres en un objeto JavaScript. Esta transformacin requiere dos cosas importantes: Qu la cadena empiece y acabe por parntesis Qu la cadena utilice la santaxis correcta de la notacin JSON. Si se cumplen las premisas anteriores la creacin de un objeto (en notacin JSON) se hara de la siguiente forma: cadena= "{ ... contenido... }" nombre_del_objeto =eval('('+cadena+')')
dnde la cadena ha de empezar por { y acabar con }, su contenido ha de respetar estrictamente la sintaxis JSON (ms adelante nos referiremos a ella) aunque por el momento no incluyamos nada y por tanto la utilizaremos para crear un objeto vaco. Para la transformacin de la cadena en objeto JavaScript utilizaremos la funcin eval() en la que incluiremos como parmetros el valor de la cadena resultante de agregar a la anterior un parntesis de apertura y otro de cierre. Cualquiera de las formas descritas permite crear objetos JavaScript tal como puedes ver en el ejemplo que encontrars un poco ms abajo.
<script type="text/javascript"> /* creamos un objeto con notacin JSON de nombre objeto1 */ var objeto1 = {}; /* creamos un objeto vaco llamado objeto 2 */ var objeto2 = new Object(); /* creamos un funcion costructora vaca*/ function constructora(){ } /* creamos un objeto por medio de la funcion anterior */ var objeto3= new constructora(); /* creamos una variable cuyo contenido es una funcion por el momento esa funcin no tendr contenidos */ var creadora= function otra_constructora(){ } /* creamos un nuevo objeto utilizando la variable creadora */ var objeto4= new creadora(); /* crearemos ahora un objeto JSON a la cadena unicamente incluye las var cadena="{}"; /* por medio de la funcion eval, previamente entre parntisis. objeto, esta vez con notacin objeto5=eval('('+cadena+')'); partir de una cadena llaves */ evaluamos la cadena anterior, incluyendola La funcin eval va a devolvernos un nuevo JSON */
/* vamos a comprobar la existencia de esos objetos (vacios) por medio de alert */ alert('El alert('El alert('El alert('El alert('El </script>
Ver ejemplo Ver cdigo fuente
el el el el el
dnde las llaves ({ }), tal como comentamos anteriormente, son obligatorias como comienzo y final del objeto y dnde las parejas"propiedad" : "valor" representan el nombre que pretendemos asignar a cada propiedad y su valor. Son obligatorios los dos puntos : que separan ambos parmetros. Cuando vayamos a incluir ms de una propiedad iremos separando mediante comas (,) las diferentes parejas propiedad valor. Cuando se trabaja en entornos de PHP cosa que ocurre cuando un objeto JSON va a ser transferido a un servidor e interpretado desde PHP) hay que tener particular cuidado con los siguientes aspectos sintcticos:
Los datos que deban ser tratados por PHP han de tener codificacn UTF-8 Utilizar siempre comillas dobles (" ") para rodear tanto nombres como valores alfanumricos Los valores numricos, booleanos y el valor null no requieren comillas En los casos en los que la creacin del objeto se realiza invocando su funcin constructura, los nombres de las propiedades y sus valores se establecen dentro de la propia funcin constructora por medio de la sintaxis: this.nombre_de_la_propiedad=valor_asignado Cuando la creacin del nuevo objeto Javascript se realiza por medio de eval() se utilizara una notacin similar a la descrita para JSON con la difrencia de que ahora, por tratarse de una cadena ha de incluirse todo entre comillas cadena= '{ "propiedad1" : "valor1", "propiedad2" : "valor2"}' nombre_del_objeto =eval('('+cadena+')') tratando siempre de usar comillas simples para las ms externas y reservando las dobles para propiedades o valores, o, si se utilizan comillas dobles para las ms externas utilizar \" en nombres y valores. En cualquiera de las opciones estaramos logrando el objetivo propuesto que no es otro que evitar las comillas simples como delimitadores de nombres de propiedades o de sus valores. Cuando los objetos JavaScript son creados por medio de una funcin constructora la asignacin de propiedades y valores puede hacerse incluyndolos en la propia funcin constructora por medio la sintaxis this.propiedad = valor
Un objeto. Requerira asignar como valor el nombre de objeto a incluir. Los valores as asignados sern identificados por la funcin tipeof (objeto.propiedad) o tipeof(variable) como object.
<html> <head> <title>Objetos JavaScript</title> <script type="text/javascript"> /* creamos un objeto con notacin JSON de nombre objeto1 incluyendo algunas propiedades*/ var objeto1 = {"var nombre":"pepe1", "pass":"pepa", "edad":26, "usuario":true, "soporte":false, "antecedentes":null, "miarray":["a",2,"b",4] }; /* creamos un objeto vaco llamado objeto 2 */ var objeto2 = new Object(); /* aqui las propiedades las agregamos invocando el objeto recien creado por medio de esta sintaxis */ objeto2.nombre="pepe2"; objeto2.pass="pepa2"; objeto2.edad=16; objeto2.usuario=false; objeto2.soporte=true; objeto2.antecedentes=25; objeto2.miarray=["a",2,"b",4]; /* creamos un funcion costructora incluyendo las propiedades y sus valores correspondientes*/ function constructora(){ this.nombre="pepe3"; this.pass="pepa3"; this.edad=36; this.usuario=false; this.soporte=true; this.antecedentes=null; this.miarray=["a",2,"b",4]; } /* creamos un objeto por medio de la funcion anterior. Se le asignarn, de forma autmatica, las propiedades incluidas en la funcion constructora */ var objeto3= new constructora(); /* creamos una variable cuyo contenido es una funcion asignndole sus propiedades despus de leer los parmetros recibidos al ser invocada la funcin. El operador ternario asinga valores por defecto a las propiedades en el caso que no sean asignados en la llamada a la funcin constructora */ var creadora= function otra_constructora(a,b,c,d,e,f,g){ (a == 'undefined' || a == null || a == '') ? this.nombre="pepe3" : this.nombre=a; (b == 'undefined' || b == null || b == '') ? this.pass="pepa3" : this.pass=b; (c == 'undefined' || c == null || c == '') ? this.edad=35 : this.edad=c; (d == 'undefined' || d == null || d == '') ? this.usuario=false : this.usuario=d; (e == 'undefined' || e == null || e == '') ? this.soporte=true : this.soporte=e; (f == 'undefined' || f == null || f == '') ? this.antecedentes=null : this.antecedentes=f; (g == 'undefined' || g == null || g == '') ? this.miarray=["a",2,"b",4] : this.antecedentes=f; }
/* creamos un nuevo objeto utilizando la variable creadora */ var objeto4= new creadora('luis','',58); /* crearemos ahora un objeto a partir de una cadena escrita con notacin JSON Evitaremos incluir saltos de lnea en la cadena. Cuando por la razn que sea necesitamos "partirla en trozos" utilizamos el operador de concatenacin (+) */ var cadena='{"nombre":"pepe5","pass":"pepa5","edad":26,'; cadena +='"usuario":true,"soporte":false,"antecedentes":null,"miarray":["a",2,"b",4]}'; /* por medio de la funcion eval, evaluamos la cadena anterior, incluyendola previamente entre parntisis. La funcin eval va a devolvernos un nuevo objeto, esta vez con notacin JSON */ objeto5=eval('('+cadena+')'); </script> </head> <body> <h3>Listado de propiedades del objeto1</h3> <!-- el bucle variable in objeto nos permitir ir recorriendo el objeto como un array. Los sucesivos valores de variable sern los nombres de las propiedades y los de objeto[variable] los valores actuales de la propiedad contenida en variable -> <script type="text/javascript"> for (i in objeto1){ document.write(i+"="+objeto1[i]+"<br />"); } </script> <h3>Listado de propiedades del objeto2</h3> <script type="text/javascript"> for (i in objeto2){ document.write(i+"="+objeto2[i]+"<br />"); } </script> <h3>Listado de propiedades del objeto3</h3> <script type="text/javascript"> for (i in objeto3){ document.write(i+"="+objeto3[i]+"<br />"); } </script> <h3>Listado de propiedades del objeto4</h3> <script type="text/javascript"> for (i in objeto4){ document.write(i+"="+objeto4[i]+"<br />"); } </script> <h3>Listado de propiedades del objeto5</h3> <script type="text/javascript"> for (i in objeto5){ document.write(i+"="+objeto5[i]+"<br />"); } </script> <h3>Agregamos una nueva propiedad y listamos el objeto1</h3> <script type="text/javascript"> objeto1.nuevapropiedad="soy la nueva"; for (i in objeto1){ document.write(i+"="+objeto1[i]+"<br />"); } </script> <h3>Modificamos una propiedad y listamos el objeto5</h3> <script type="text/javascript"> objeto5.nombre="Me han cambiado de nombre"; for (i in objeto5){ document.write(i+"="+objeto5[i]+"<br />");
Cuidado! Es importante descargar el fichero comprimido al que se accede desde este enlace. Cuando hemos descargado directamente el fichero json2.js desde este otro enlace hemos tenido problemas porque al parecer este ltimo fichero tiene errores. En cualquier caso, para facilitarte la labor, en este enlace tienes un fichero llamado json2.zip con la versin correcta de json2.js.
En el ejemplo que tienes a continuacin puedes ver la forma de utilizar estos recursos. Presta atencin a los comentarios porque es muy importante tener en cuenta las peculiaridades de la sintaxis para lograr un aceptable grado de compatibilidad entre navegadores.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>JSON</title> <script type="text/javascript"> /* Comprobamos la existencia del objeto JSON. Si existe es que la versin del navegador lo incluye. Si no existe el objeto JSON incluimos el fichero externo json2.js La particular manera de partir las palabra script tiene como finalidad evitar errores del navegador al interpertar ya que se presenta una confusin
al desconocer si debe tratarlo como una cadena o como un script que deba ejecutarse. La cabecera <!DOCTYPE HTML PUBLIC ... es imprescindible en este caso ya que el navegador IE dar un error JSON no est definido en el caso de no incluirla*/ if (typeof(JSON)==="undefined"){ alert('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); document.write('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); }else{ document.write("No es necesario el json2.js externo. El navegador incluye JSON<br>"); } /* Cuidado! la etiqueta script debe cerrarse aqu, despus de la comprobacin y abrirse nuevamente para continuar con el resto de las instrucciones. De esta forma el fichero JSON ya estar disponible cuando se acceda desde el bloque que insertamos a continuacin */ </script> <script type="text/javascript"> /* creamos la cadena con las propiedades y valores del objeto */ var cadena='{"nombre":"pepe5","pass":"pepa5","edad":26,"usuario":true,"soporte":false,'; cadena+='"antecedentes":null,"miarray":["a",2,"b",4]}'; /* utilizamos el mtodo parse para crear el objeto */ objeto=JSON.parse(cadena); /* visualizamos las propiedades del objeto */ document.write("<br>Estas son las propiedade del objeto JSON<br>"); for (i in objeto){ document.write(i+"="+objeto[i]+"<br />"); } /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br>El objeto JSON convertido en cadena por JSON.stringify<br>"); document.write(JSON.stringify(objeto)); /* utilizaremos el segundo parmetro de la funcion para que invoque una funcion llamada funcion_opcional Esta vez no lleva los () porque lo que pretendemos de esa funcion no es que nos devuelva un valor sino que se ejecute*/ var objeto1 = JSON.parse(cadena, funcion_opcional); /* la llamada a la funcin opcional se har reiterativamente mientras va recorriendo todos los pares propiedad:valor que son recibidos en la llamada a la funcin */ function funcion_opcional(propiedad, valor) { /* si el valor es tipo cadena le aadimos un texto delante */ if (typeof valor === 'string') { return "Añadido + "+ valor; } /* si el valor es tipo boleano lo ponemos como false */ if (typeof valor === 'boolean') { return false; } /* si es tipo numero le multiplicamos por 7 */ if (typeof valor === 'number') { return valor*7; } /* si el valor es null lo cambiamos por 45 */ if (valor==null){ return 45; } /* si el valor no es de los tipos anteriores lo devuelve sin modificar */
return valor; } /* listamos las propiedades del objeto resultante */ document.write("<br>Listado de propiedades del objeto JSON modificado<br>"); for (i in objeto1){ document.write(i+"="+objeto1[i]+"<br />"); } /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br>El objeto modificado convertido en cadena por JSON.stringify<br>"); document.write(JSON.stringify(objeto1)+"<br><br>"); /* el metodo JSON.strinfgify es aplicable a cualquier objero JavaScript Crearemos un objeto incluyendo propiedades de todo tipo */ var una_matriz=new Array('Aviles','Oviedo','Gijn'); var otro_objeto= function crea_objeto(){ this.propiedad1="valor1"; this.propiedad2=45; this.propiedad3=true; this.propiedad4=null this.objeto_incluido=objeto; this.otro_objeto=objeto1; this.matriz=[1,2,"a","b"]; this.matriz2=una_matriz; } objeto_complejo=new otro_objeto(); /* listamos los tipos y valores de las propiedades del objeto resultatne*/ for (i in objeto_complejo){ document.write(typeof(objeto_complejo[i])+"-->"); document.write(i+"="+objeto_complejo[i]+" "); } document.write('<br><br>Listamos las propiedades, tipos y valores del objeto'); document.write(' incluido como propiedad en el objeto principal<br>'); for (i in objeto_complejo.objeto_incluido){ document.write(typeof(objeto_complejo.objeto_incluido[i])+"-->"); document.write(i+"="+objeto_complejo.objeto_incluido[i]+"<br>"); } /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante<br><br>"); document.write(JSON.stringify(objeto_complejo)); </script> </head> <body> </body> </html>
Ver ejemplo
Entendemos como funcin annima aquella que es definida sin incluir ningn nombre de la funcin. Tendra por tanto una estructura del tipo: function () { ... instrucciones } Este tipo de funciones pueden incluidas como mtodos de un objeto JavaScript de una de las formas siguientes: Incluyndolas en un funcin constructora invocable directamente para crear un objeto. function constructora(){ ... instrucciones en la funcin constructora this.mi_metodo = function(){ ... instrucciones de la funcin annima } ... instrucciones en la funcin constructora } El metodo se invoca utilizando la sintaxis: objeto= new constructora(); objeto.mi_metodo(); Antes de invocar el mtodo debe haber sido creado un objeto y el mtodo se invoca (y esto es muy importante) agregando parntesis () despus del nombre del mtodo. En este caso el resultado de la ejecucin del mtodo sera el resultado de la ejecucin de la funcin annima. Si se invocara el mtodo sin agregar los parntesis () finales lo que se obtendra sera un copia de la funcin annima pero no el resultado de su ejecucin. Incluyndolas en la funcin constructora incluida como contenido de una variable. variable =function constructora(){ ... instrucciones en la funcin constructora this.mi_metodo = function(){ ... instrucciones de la funcin annima } ... instrucciones en la funcin constructora } El metodo se invoca utilizando la sintaxis: objeto= new variable(); objeto.mi_metodo(); Este caso es una leve variante del anterior. La nica diferencia es que ahora la funcin constructora est asignada a una variable. Por tanto, para crear un objeto se invoca tal variable en vez de invocar a la funcin como ocurra en el caso anterior. El resto de los comentarios del caso anterior, incluidos los relativos a los parntesis () siguen siendo vlidos en este supuesto. Agregndolas a un objeto JavaScript ya creado. objeto =new Object(); objeto.mi_metodo = function(){ ... instrucciones de la funcin annima } El metodo se invoca utilizando la sintaxis: objeto.mi_metodo(); Este supuesto nos permite visualizar la importancia de los mencionados parntesis. Cuando lo escribimos sin parntesis le estamos asignando (o leyendo) la funcion annima. Sin embargo, cuando le agregamos los parntesis le estamos solicitando que nos devuelva el resultado de la ejecucin de la funcin En este ejemplo puedes ver las distintas opciones de definir mtodos utilizando funciones annimas.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>)Objetos JavaScript</title>
<script type="text/javascript"> /* comprobamos en un script independiente si JSON es soportado nativamente y en caso contrario carga el fichero correspondiente */ if (typeof(JSON)== "undefined"){ alert('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); document.write('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); } /* continuamos escribiendo el cdigo JavaScript pero incluyndolo dentro de una nuevas etiquetas */ </script> <script type="text/javascript"> function crea_objeto1(){ this.nombre="soy el objeto 1"; /* defino un mtodo por medio de una funcin annima (observa que entre function y () no lleva ningn nombre de ah lo de annima incluida dentro de la propia funcion constructora */ this.metodo1=function(){ return (5*3); } /* escribirlo as es pura redundancia ya que la propiedad1 y el mtodo1 son la misma cosa */ this.propiedad1=this.metodo1; /* esto ya es diferente. La propiedad2 tomar el valor resultante de la ejecucin del mtodo, es decir 15*/ this.propiedad2=this.metodo1(); } /* creamos un objeto utilizando la funcion constructora crea_objeto1 */ objeto1=new crea_objeto1(); document.write("<h3>Utilizando una funcin constructora</h3>"); document.write("<br><br>Probando la funcin annima<br><br>"); document.write("Soy el resultado de this.metodo1 leido desde la propiedad1 = "); document.write(objeto1.propiedad1+"<br>"); document.write("Soy el resultado de objeto1.metodo1 = "); document.write(objeto1.metodo1+"<br>"); document.write("Soy el resultado de this.metodo1() leido desde la propiedad2 = "); document.write(objeto1.propiedad2+"<br>"); document.write("Soy el resultado de objeto1.metodo1() = "+objeto1.metodo1()+"<br><br>"); document.write("Soy el resultado de objeto1.metodo1() = "); document.write(objeto1.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante"); document.write(" (slo transforma propiedades)<br><br>"); document.write(JSON.stringify(objeto1)+"<br>"); /* ahora la funcion constructora ser una funcin annima asignada a la variable que hemos llamado trabajadora */ var trabajadora=function (){ this.nombre="Yo soy el objeto creado por la trabajadora"; /* defino un mtodo por medio de una funcin annima (observa que entre function y () no lleva ningn nombre de ah lo de annima incluida dentro de la propia funcion constructora */ this.metodo1=function(){ return (25-3); } this.propiedad1=this.metodo1; this.propiedad2=this.metodo1();
} /*creamos el nuevo objeto utilizando la variable trabajadora */ objeto2=new trabajadora(); document.write("<h3>Utilizando una variable que contiene la funcin constructora</h3>"); document.write("<br><br>Probando la funcin annima<br><br>"); document.write("Soy el resultado de this.metodo1 leido desde la propiedad1 = "); document.write(objeto2.propiedad1+"<br>"); document.write("Soy el resultado de objeto2.metodo1 = "); document.write(objeto2.metodo1+"<br>"); document.write("Soy el resultado de this.metodo1() leido desde la propiedad2 = "); document.write(objeto2.propiedad2+"<br>"); document.write("Soy el resultado de objeto2.metodo1() = "); document.write(objeto2.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante"); document.write(" (slo transforma propiedades)<br><br>"); document.write(JSON.stringify(objeto2)+"<br>"); document.write("<h3>Utilizando new Object()</h3>"); objeto3=new Object(); /* asignamos un mtodo al objeto recin creado */ objeto3.metodo1=function(){ return "Soy le resultado del metodo1 (anonimo) en el objeto3"; } /* visualizamos los elementos del nuevo objeto. */ document.write("Soy el resultado de objeto3.metodo1 = "); document.write(objeto3.metodo1+"<br>"); document.write("Soy el resultado de objeto3.metodo1() = "); document.write(objeto3.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante<br>"); document.write("Como slo transforma propiedades no tiene contenidos<br><br>"); document.write(JSON.stringify(objeto3)+"<br>"); </script> </head> <body> </body> </html>
Ver ejemplo
function externa () { ... instrucciones } Tambin puede se utilizada en los tres supuestos planteados para las funciones annimas. Incluyndolas en un funcin constructora invocable directamente para crear un objeto. function constructora(){ ... instrucciones en la funcin constructora this.mi_metodo = externa ... instrucciones en la funcin constructora } El metodo se invoca utilizando la sintaxis: objeto= new constructora(); objeto.mi_metodo(); Cuando desde this.mi_metodo se invoca la funcin constructora no se ponen parntesis dado que en este caso no pretendemos que se ejecute la funcin sino que se agregue su contenido al mtodo que estamos creando. Una vez creado el mtodo se invoca exactamente igual que hacamos cuando se trataba de funciones annimas Incluyndola en la funcin constructora incluida como contenido de una variable. variable =function constructora(){ ... instrucciones en la funcin constructora this.mi_metodo = externa ... instrucciones en la funcin constructora } El metodo se invoca utilizando la sintaxis: objeto= new variable(); objeto.mi_metodo(); Son vlidos los mismos comentarios realizados en el supuesto anterior. Agregndolas a un objeto JavaScript ya creado. objeto =new Object(); objeto.mi_metodo = constructora El metodo se invoca utilizando la sintaxis: objeto.mi_metodo(); Tambin aqu tienen plena validez los comentarios relativos a la no inclusin de parntesis detrs del nombre de la funcin externa cuando se trata de crear un nuevo mtodo En este ejemplo puedes ver las distintas opciones de definir mtodos utilizando una funcin externa.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>)Objetos JavaScript</title> <script type="text/javascript"> /* comprobamos en un script independiente si JSON es soportado nativamente y en caso contrario carga el fichero correspondiente */ if (typeof(JSON)== "undefined"){ alert('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); document.write('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); } /* continuamos escribiendo el cdigo JavaScript pero incluyndolo dentro de una nuevas etiquetas */ </script> <script type="text/javascript"> /* esta sera la funcin externa */ function externa(){
return "Solo el resultado de la funcion externa"; } /* funcion constructora */ function crea_objeto1(){ this.nombre="soy el objeto 1"; /* defino un mtodo por medio de la funcin externa a la que llamamos sin agregar los parntesis finales*/ this.metodo1=externa; /* escribirlo as es pura redundancia ya que la propiedad1 y el mtodo1 son la misma cosa */ this.propiedad1=this.metodo1; /* esto ya es diferente. La propiedad2 tomar el valor resultante de la ejecucin del mtodo */ this.propiedad2=this.metodo1(); } /* creamos un objeto utilizando la funcion constructora crea_objeto1 */ objeto1=new crea_objeto1(); document.write("<h3>Utilizando una funcin constructora</h3>"); document.write("<br><br>Probando la funcin externa<br><br>"); document.write("Soy el resultado de this.metodo1 leido desde la propiedad1 = "); document.write(objeto1.propiedad1+"<br>"); document.write("Soy el resultado de objeto1.metodo1 = "); document.write(objeto1.metodo1+"<br>"); document.write("Soy el resultado de this.metodo1() leido desde la propiedad2 = "); document.write(objeto1.propiedad2+"<br>"); document.write("Soy el resultado de objeto1.metodo1() = "+objeto1.metodo1()+"<br><br>"); document.write("Soy el resultado de objeto1.metodo1() = "); document.write(objeto1.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante"); document.write(" (slo transforma propiedades)<br><br>"); document.write(JSON.stringify(objeto1)+"<br>"); /* ahora la funcion constructora ser una funcin annima asignada a la variable que hemos llamado trabajadora */ var trabajadora=function (){ this.nombre="Yo soy el objeto creado por la trabajadora"; /* defino un mtodo por medio de la funcion externa */ this.metodo1=externa this.propiedad1=this.metodo1; this.propiedad2=this.metodo1(); } /*creamos el nuevo objeto utilizando la variable trabajadora */ objeto2=new trabajadora(); document.write("<h3>Utilizando una variable que contiene la funcin constructora</h3>"); document.write("<br><br>Probando la funcin externa<br><br>"); document.write("Soy el resultado de this.metodo1 leido desde la propiedad1 = "); document.write(objeto2.propiedad1+"<br>"); document.write("Soy el resultado de objeto2.metodo1 = "); document.write(objeto2.metodo1+"<br>"); document.write("Soy el resultado de this.metodo1() leido desde la propiedad2 = "); document.write(objeto2.propiedad2+"<br>");
document.write("Soy el resultado de objeto2.metodo1() = "); document.write(objeto2.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante"); document.write(" (slo transforma propiedades)<br><br>"); document.write(JSON.stringify(objeto2)+"<br>"); document.write("<h3>Utilizando new Object()</h3>"); objeto3=new Object(); /* asignamos un mtodo al objeto recin creado */ objeto3.metodo1=externa /* visualizamos los elementos del nuevo objeto. */ document.write("Soy el resultado de objeto3.metodo1 = "); document.write(objeto3.metodo1+"<br>"); document.write("Soy el resultado de objeto3.metodo1() = "); document.write(objeto3.metodo1()+"<br>"); /* ahora creamos una cadena JSON a partir del contenido del objeto */ document.write("<br><br>Cadena JSON del objeto resultante<br>"); document.write("Como slo transforma propiedades no tiene contenidos<br><br>"); document.write(JSON.stringify(objeto3)+"<br>"); </script> </head> <body> </body> </html>
Ver ejemplo
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head>
<title>)Objetos JavaScript</title> <script type="text/javascript"> /* comprobamos en un script independiente si JSON es soportado nativamente y en caso contrario carga el fichero correspondiente */ if (typeof(JSON)== "undefined"){ alert('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); document.write('<sc'+'ript type="text/javascript" src="json2.js">'+'</sc'+'ript>'); } /* continuamos escribiendo el cdigo JavaScript pero incluyndolo dentro de una nuevas etiquetas */ </script> <script type="text/javascript"> /* esta sera la funcin externa */ function externa(){ return "Solo el resultado de la funcion externa"; } /* funcion constructora la defino vaca*/ function crea_objeto1(){ } /* agregamos un nuevo mtodo -en este caso una funcion annimaa la funcin constructora anterior */ crea_objeto1.prototype.metodo1 = function() { return ("Esta es la funcion anonima incluida como metodo 1"); } /* agregamos un segundo mtodo -en este caso una funcion externaa la funcin constructora anterior */ crea_objeto1.prototype.metodo2 = externa; /* creamos un objeto utilizando la funcion constructora crea_objeto1 */ objeto1=new crea_objeto1(); /* ejecutamos ambos mtodos con y sin parntesis */ document.write("Soy el resultado de objeto1.metodo1 = "); document.write(objeto1.metodo1+"<br>"); document.write("Soy el resultado de objeto1.metodo1() = "); document.write(objeto1.metodo1()+"<br>"); document.write("Soy el resultado de objeto1.metodo2 = "); document.write(objeto1.metodo2+"<br>"); document.write("Soy el resultado de objeto1.metodo2() = "); document.write(objeto1.metodo2()+"<br>"); /* ahora la funcion constructora ser una funcin annima asignada a la variable que hemos llamado trabajadora. Tambien la crearemos vaca*/ var trabajadora=function (){ } /* agregamos un nuevo mtodo -en este caso una funcion annimaa la variable anterior */ trabajadora.prototype.metodo1 = function() { return ("Esta es otra funcion anonima incluida como metodo 1 en trabajadora"); }
/* agregamos un segundo mtodo -en este caso una funcion externaa la variable trabajadora */ trabajadora.prototype.metodo2 = externa; /* creamos un objeto utilizando la variable trabajadora */ objeto2=new trabajadora(); /* ejecutamos ambos mtodos con y sin parntesis */ document.write("Soy el resultado de objeto2.metodo1 = "); document.write(objeto2.metodo1+"<br>"); document.write("Soy el resultado de objeto2.metodo1() = "); document.write(objeto2.metodo1()+"<br>"); document.write("Soy el resultado de objeto2.metodo2 = "); document.write(objeto2.metodo2+"<br>"); document.write("Soy el resultado de objeto2.metodo2() = "); document.write(objeto2.metodo2()+"<br>"); </script> </head> <body> </body> </html>
Ver ejemplo
Una vez conocemos los rudimentos de los objetos en JavaScript y dado que tambin hemos manejado los objetos PHP ya estaremos en condiciones de afrontar la labor de intercambiar objetos entre ambos lenguajes y, por lo tanto, intercambiar objetos entre cliente y servidor y tambin entre servidor y cliente. Ser lo que afrontaremos en la pgina siguiente.