[go: up one dir, main page]

0% encontró este documento útil (0 votos)
357 vistas246 páginas

Manual de PHP

1) Los servidores son ordenadores remotos que ofrecen servicios como páginas web, correo electrónico, etc. mediante programas de servidor específicos. 2) Los clientes son programas como navegadores web e Outlook que realizan peticiones a los servidores y reciben respuestas. 3) Las páginas web pueden ser estáticas, con contenido fijo, o dinámicas, con contenido que puede cambiar según las acciones del usuario o el servidor.

Cargado por

userjcor
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
357 vistas246 páginas

Manual de PHP

1) Los servidores son ordenadores remotos que ofrecen servicios como páginas web, correo electrónico, etc. mediante programas de servidor específicos. 2) Los clientes son programas como navegadores web e Outlook que realizan peticiones a los servidores y reciben respuestas. 3) Las páginas web pueden ser estáticas, con contenido fijo, o dinámicas, con contenido que puede cambiar según las acciones del usuario o el servidor.

Cargado por

userjcor
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 246

Páginas WEB dinámicas

Servidores y clientes

Es frecuente observar, en la calle, que son muchas las personas que cuando se refieren a los servidores lo hacen
como sí se tratara de máquinas complejísimas, misteriosas, lejanas y enormes que, bajo esa aureola de cripticismo,
parecen totalmente distintas al ordenador que usamos habitualmente. ¡Nada más lejos de la realidad!

Vamos a intentar aclarar algunos conceptos con ejemplos cotidianos. Pensemos en esos ordenadores remotos
(también llamados host) como si se tratara de uno esos sitios desde los que se sirven comidas a domicilio.

Quizá lo primero en lo que se te ocurra pensar sea en una pizza, no porque desconozcas que también 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 páginas web hace que tendamos a identificarlos con ellas, pero también
los host ofrecen –o pueden ofrecer– más 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 instalación
frigorífica.

Pues bien, algo muy similar ocurre con los host. También éstos pueden ofrecer uno o varios servicios (páginas
web, correo electrónico, transferencias FTP, noticias, etcétera) y también es necesario que cada servicio disponga de su
propia infraestructura, que en este caso sería un programa distinto (software de servidor) para cada uno de ellos.

Como puedes ver, no basta con hablar de servidores. Es necesario especificar también qué es lo que sirven.Habría
que decir: servidor de páginas web, servidor de correo, etcétera y tener presente que –aunque convivan en la misma
máquina– cada uno de ellos requiere su propio software y su propia configuración.

Resumiendo, cuando en lenguaje coloquial hablamos de un servidor estamos aludiendo un host (ordenador
remoto) –el tamaño y la lejanía 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 cómo se desarrolla ese proceso de petición–respuesta. Para leer el correo electrónico
necesitas disponer de un programa –supongamos que es Outlook Express– instalado en tu ordenador y hacer, a través
de él, una petición a un ordenador remoto (host). Si quisieras visualizar páginas web tendrías que utilizar un programa
distinto –Firefox o Internet Explorer, por ejemplo– capaz de realizar esta otra tarea. Al programa que utilizamos para
realizar cada petición le llamaremos cliente.

¿Qué es una petición?

Una petición es un conjunto de datos que un cliente (recuerda que el cliente siempre es uno de los programas
instalados en tu ordenador) envía a través de Internet solicitando una respuesta determinada por parte de
un servidor (ordenador remoto).

¿Qué contendría esa petición?

Cada tipo de petición tendrá contenidos distintos. Por ejemplo, cuando se trata de leer mensajes de correo, la
petición realizada por el cliente (Outlook Express) contendría, entre otros, muchos de los datos de la configuración de la
cuenta, tales como: el protocolo (forma de comunicación) –en el caso del correo lo habitual sería el
protocolo POP (Post Office Protocol)–, el nombre de host donde está alojado el buzón (servidor POP ó servidor de correo
entrante), el nombre de la cuenta, la contraseña de acceso, y algunas otras informaciones relativas a la gestión de esa
cuenta tales como si deben conservarse o no los mensajes en el servidor, etcétera.

¿Qué ocurre con esa petición?

Cualquier petición pasa en primera instancia por un servidor de nombres de dominio (Domain Name Server) DNS,
una especie de guía telefónica que contiene los nombres de los servidores y las direcciones IP a través de las cuales
están conectados a Internet. Podría decirnos –los datos son ficticios– que olmo.cnice.mecd.es es el nombre de
un host que está conectado a Internet a través de la dirección IP 111.112.113.114

Pág. 1
Una vez resuelta esa petición por el servidor DNS (direccionamiento de la petición a la IP correspondiente) se
comprobará si esa IP está activa (si efectivamente hay un ordenador conectado a través de ella) y, en caso de estarlo, se
determinará si ese ordenador al que estamos accediendo es capaz de atender la petición.

¿Qué tiene que ocurrir para que pueda atenderse una petición?

Es necesario que el ordenador remoto tenga instalado y funcionando el software de servidor adecuado al protocolo
de nuestra petición. Ello quiere decir –siguiendo con el ejemplo– que el ordenador remoto debe tener instalado y
funcionando un software específico de servidor de correo capaz de interpretar el protocolo POP3 especificado en la
petición.

¡Cuidado!

El ordenador remoto debe tener instalado y funcionando el software adecuado a cada tipo de petición
(servicio) que deba atender. No basta con decir servidor, es preciso conocer los servicios que presta y es
factible que un mismo ordenador preste –simultáneamente– varios servicios, siempre que tenga instalado
y activo el software específico para cada uno de esos servicios.

Cuando el ordenador remoto acepta la petición 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 petición
(comprobar que el nombre de la cuenta y la contraseña son correctas, comprobar si existen mensajes, borrarlos del buzón
si así lo especifica la petición, etc.) y devuelven al cliente (recuerda que el cliente era nuestro Outlook Express) la
información requerida.

Solo falta que una vez recibida la respuesta Outlook Express (cliente) interprete la información recibida y nos
permita visualizar o imprimir el contenido de los mensajes descargados del servidor.

Servidor y cliente en una misma máquina

Hasta ahora –al referirnos a servidores y clientes– hemos hecho alusión a dos máquinas: nuestro propio
ordenador (ordenador local) en el que estarían instaladas las aplicaciones cliente y un ordenador remoto en el que se
alojarían las aplicaciones de servidor. Eso es lo más habitual, pero no es la única posibilidad. Dado que servidor y cliente
son únicamente aplicaciones, es perfectamente posible que ambas convivan dentro de la misma máquina.

La diferencia sustancial sería que ahora no es necesario el servidor de DNS para buscar la dirección IP.
Utilizaríamos una IP (habitualmente la 127.0.0.1) reservada para estos casos –preestablecida en la configuración del
servidor– y a través de ella se canalizarían las peticiones a nuestro propio servidor. Ya hablaremos más adelante de esta
IP.

Tipos de páginas web

Una de las clasificaciones más simples de las páginas web permitiría agruparlas en dos
tipos: estáticas y dinámicas.

Páginas web estáticas

Diremos que una página web es estática cuando sus contenidos no son susceptibles de ser modificados ni
por intervención del usuario ni por una acción automática del servidor (ordenador remoto) ni del cliente (navegador).

Un ejemplo de página estática

Cualquier usuario que acceda a esta página que incluimos como ejemplo –ya sea en modo local, o a través de un
servidor remoto– visualizará siempre la misma fecha: 22 de setiembre de 2011.

<html>
<head>
</head>
<body>
Hoy es 03-10-2015 y son las 08:23:37 horas
Pág. 2
</body>
</html>

ejemplo1.html

Las peticiones de páginas estáticas 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 ningún servidor– eres capaz de visualizar tus propias páginas web sin más hacer un doble clic sobre su icono.
Eso es cierto, pero fíjate 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
dirección una ruta (el path que conduce hasta el documento) mientras que en la de la derecha aparece el sintagma http al
principio de la dirección.

Pág. 3
En el primer caso no hemos hecho ninguna petición de página web sino que hemos abierto un documento cuya
extensión (html) está asociada en nuestra configuración 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 hubiéramos hecho
doble clic sobre el icono de un documento con extensióntxt, con la única salvedad de que en este último caso se habría
abierto el bloc de notas (por la asociación de extensiones y aplicaciones en la configuración de Windows).

En el segundo caso las cosas son distintas. Se incluye el sintagma http – acrónimo
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 petición sea capaz de interpretarlo. Por eso a los servidores que alojan páginas web se les suele
llamar servidores web o servidores HTTP dado que se les requiere que soporten este protocolo.

Páginas dinámicas

Llamaremos dinámicas a las páginas cuyos contenidos sí pueden ser modificados –de forma automática o
mediante la intervención de un usuario– bien sea desde el cliente y/o desde el servidor.

Para que una modificación de este tipo pueda producirse es necesario que algo o
alguien especifique: qué, cómo, cuándo, dónde 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 modificación. 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 intérprete capaz de ejecutarlas.

Somos capaces de entender unas instrucciones escritas en castellano pero si estuvieran escritas en búlgaro las
cosas seguramente serían bastante distintas, y, por supuesto, a un búlgar@ le pasaría justamente lo contrario. Igual
ocurre con los programas intérpretes de los lenguajes de script. Ellos también 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 página WEB de modo que su intérprete pueda acceder a ellas en el momento en el que se requiera su ejecución.

Cuando se incrustan scripts en una página WEB empiezan a convivir dentro de un mismo documento
informaciones destinadas a distintos intérpretes. Por una parte, el código HTML que ha de ser interpretado por el
navegador, y por la otra, los scripts que han de ser ejecutados por el intérprete 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 señalando el final con una etiqueta de cierre </script>.

Lo que no está contenido entre esas etiquetas será considerado código HTML.

La posibilidad de insertar en un mismo documento scripts escritos en distintos lenguajes obliga a especificar cuál
se ha utilizado en cada caso, para que en el momento en el que vayan a ser ejecutados se invoque el intérprete 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>

indicaría que las instrucciones están escritas con la sintaxis de PHP. Por el contrario, al escribir:

<script language="JavaScript">
......
...... instrucciones ..
......
</script>

Pág. 4
estaríamos señalando que en las instrucciones contenidas en el script utilizan sintaxis de JavaScript. La alternativa más
reciente (la anterior está obsoleta) sería:<script type="text/javascript">

Para el caso concreto de PHP, existe una sintaxis alternativa, mucho más cómoda y habitual. Es la siguiente:

<?php
......
......instrucciones..
......
?>

Aquí <?php hará la misma función que <script language="PHP"> y ?> será equivalente a </script>. Con la
configuración adecuada también podríamos usar <? –en vez de <?php– como marca inicial.

Lenguajes de script

Hay múltiples posibilidades en cuanto a lenguajes de script. Pero antes de hacer mención a algunos de ellos es
conveniente hacer una clasificación previa. Hablaremos de dos tipos: lenguajes del lado del cliente y lenguajes del
lado del servidor.

Lenguajes del lado del cliente

Diremos que un lenguaje es del lado del cliente cuando el intérprete que ha de ejecutar sus scripts es accesible
desde éste –el cliente– sin que sea necesaria ninguna intervención en este sentido por parte servidor.

Seguramente te ha ocurrido alguna vez que al intentar acceder a una página web ha aparecido un mensaje
advirtiendo que para la correcta visualización de la página se requiere un plug-in determinado, y que, a la vez, se te haya
ofrecido la posibilidad de descargarlo en ese momento. Eso ocurre porque cuando el navegador –que en el caso de las
páginas web es el cliente– trata de interpretar la página, encuentra incrustado en ella algo (un fichero de sonido, una
animación Flash, etcétera) que –de forma muy similar a lo que ocurre con los scripts– requiere un intérprete adecuado del
que no dispone en ese momento. Cuando los scripts contenidos en un documento son de este tipo, el servidor lo entrega
al cliente si efectuar ningún tipo de modificación.

Sin pretender hacer una enumeración exhaustiva, entre los lenguajes de script del lado del cliente los más
populares son: DHTML, JavaScript y VBScript.

DHTML no es exactamente un lenguaje de programación. Se trata más bien de una serie de capacidades que se
han ido añadiendo a los navegadores modernos mediante las cuales las páginas pueden contener hojas de estilo y/o
organizarse en capas susceptibles de ser modificadas, redimensionadas, desplazadas y/o ocultadas.

JavaScript es uno de los lenguajes más populares. Cada navegador incluye su propio intérprete y es frecuente
que los resultados de visualización sean algo distintos según el navegador y la versión que se utilice. Parece ser que las
versiones más recientes de los distintos navegadores se aproximan a un estándar –ECMA Script-262– que ha sido
desarrollado por la ECMA (Asociación Europea de Normalización de Sistemas de Información y Comunicación), lo que
hace suponer que en un futuro muy próximo todos los navegadores se ajustarán a esa especificación y que, con ello, las
páginas web ya se visualizarán de forma idéntica en todos ellos.

VBScript es un lenguaje de script derivado de VisualBasic y diseñado por Microsoft para Internet Explorer y los
navegadores derivados o vinculados a este. Una petición de página en la que hay incrustados scripts escritos en lenguaje
del lado del cliente se realizaría de una forma similar a esta:

Pág. 5
Como puedes observar no requiere nada distinto a lo del supuesto anterior. La diferencia sería que en este caso
se harían llamadas al intérprete 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 páginas web dinámicas. Ambas utilizan los JavaScript que puedes ver en rojo en su
código fuente. Si pulsas en el enlace del primero de estos dos ejemplos verás que la fecha que aparece en la página es
la fecha actual de tu sistema, y además, cada vez que pulses el botón Actualizar de tu navegador comprobarás que esa
intervención 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 modificación de los contenidos no requiere intervención alguna por parte del usuario. Cada 5
segundos (fíjate donde dice var frecuencia=5000). Cinco mil es el período de actualización, expresado en milisegundos)
se rescribirán de forma automática la fecha y la hora. Tenemos por tanto una especie de cronómetro automático.
<html>
<head>
<script type="text/javaScript">
var reloj=0;
var frecuencia=5000;
function actualiza(){
var son= new Date();

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

ejemplo3.html

Lenguajes del lado del servidor

Un lenguaje es del lado del servidor cuando la ejecución de sus scripts se efectúa, por instancia de este –el
servidor–, antes de dar respuesta a la petición, de manera que el cliente no recibe el documento original sino el resultante
de esa interpretación previa.

Cuando se usan estos tipos de lenguaje el cliente recibe un documento en el que cada script contenido en el
original habrá sido sustituido por los resultados de su ejecución. Esto es algo a tener muy en cuenta, porque, en este
caso, los usuarios no tendrán la posibilidad de visualizar el código fuente, mientras que cuando se trata de lenguajes del
lado del cliente siempre es posible visualizar los scripts, bien sea de forma directa –mirando el código fuente de la página
recibida– o leyendo el contenido de ficheros externos –vinculados a ella– que son bastante fáciles de encontrar en la
caché del navegador. La utilización de este tipo de scripts requiere que el intérprete del lenguaje sea accesible –esté del
lado– desde el propio servidor.

Entre los lenguajes del lado del servidor los más populares son: PHP, ASP, PERL y JSP. Cada uno de ellos tiene
sus propias peculiaridades. No abundaremos en ellas. Nosotros trataremos aquí sobre PHP.

Las posibles dudas del servidor

Dado que en unos casos el servidor debe entregar el documento original –páginas estáticas o páginas dinámicas
en las que se usan lenguajes del lado del cliente– mientras que en otros casos –páginas dinámicas usando lenguajes del
lado del servidor– tiene que devolver el resultado de la ejecución de los scripts, es razonable que te preguntes: ¿cómo
sabe el servidor lo que debe hacer en cada caso?

La respuesta es simple. Eso hay que decírselo. Y se le dice de una forma bastante simple. Se indica al poner la
extensión al documento. Si en la petición se alude a un documento con extensión .htm o .html el servidor entenderá que
esa página no requiere la intervención previa de ningún intérprete de su lado y entregará la página tal cual.

Si en esa petición se aludiera a una extensión distinta –.php, por ejemplo– el servidor entendería que antes de
servir la página debe leerla y requerir al intérprete de PHP que ejecute los scripts desarrollados en ese lenguaje (en caso
de que los contuviera) y devolvería al cliente el documento que resultara de las eventuales ejecuciones de tales scripts.

Aquí tienes el esquema de un ejemplo de convivencia en un mismo documento de varios scripts y varios tipos de
lenguaje.

Pág. 7
Aquí ya es preciso que, además de un servidor capaz de soportar el protocolo HTTP, esté instalado –del lado del
servidor– un intérprete PHP, un servidor de bases de datos MySQL y que, además, estén 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 más potentes y populares que existen en este momento.

Requisitos para el uso del lenguaje PHP

De acuerdo a lo comentado en los párrafos anteriores el uso del lenguaje PHP requiere tener instalado y
configurado:

 Un software de servidor web –configurado para interactuar con el intérprete de PHP– que soporte el protocolo HTTP
y que en nuestro caso será el denominado servidor Apache.
 El intérprete de PHP.
 Un software de servidor de bases de datos capaz de ser gestionado mediante funciones propias de PHP. Podemos
utilizar el servidor de bases de datos MySQL o su «fork» MariaDB (¡me gustó eso del fork!) y también podrás
encontrar referencias al uso deSQLite que en muchos casos puede resultar una alternativa más ligera y accesible.

Pág. 8
PHP y HTML

Páginas PHP

Las páginas PHP pueden ser páginas web normales a las que únicamente se les cambia la extensión tradicional
(.htm ó .html) , por la extensión .php. Observemos este código fuente. Como verás, se trata de una página web muy
simple que no contiene ningún script PHP.

<html>
<head>
<title>Aprendiendo PHP</title></head>
<body>
Esta es una página supersimple
</body>
</html>

Hemos guardado esa página 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 página cuyo nombre tenga por extensión .php se pueden insertar instrucciones –escritas en lenguaje
PHP– anteponiendo <?php a la primera instrucción y escribiendo ?> después de la última. A cada uno de estos bloques
de instrucciones le llamaremos un script. No existe límite en cuanto al número de scripts distintos que pueden insertarse
dentro de una página.

La primera instrucción PHP que conoceremos será esta:

echo "un texto...";.

La instrucción echo seguida de un texto entrecomillado hará que el PHP escriba en la página web resultante lo
contenido en esa cadena de texto. Al final de cada instrucción debemos insertar siempre un punto y coma (;). Este signo
(;) indicará a PHP que lo que viene a continuación es una nueva instrucción.

Para facilitar la depuración de los scripts no suelen escribirse dos instrucciones en una misma línea.

print "un texto ...";

La instrucción print tiene una función similar –no es exactamente la misma– a la descrita para echo. Más adelante
veremos algunas de sus diferencias.

print ("un texto...");

Esta es otra manera –la más habitual– de utilizar print. Ahora encerramos entre paréntesis la cadena que
pretendemos que aparezca impresa en la página web. El hecho de que utilicemos paréntesis no evita la obligación 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 minúsculas). Cuando es
preciso anidar comillas deben utilizarse tipos distintos para las exteriores y para las interiores.

Para que una instrucción 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 ningún caso –ni

Pág. 9
con echo ni con print– está permitido sustituir las comillas exteriores (las que encierran la cadena) por \". Esta sintaxis
solo es válida para indicar a PHP que debe interpretar las comillas como un carácter más.

En la página siguiente veremos las diferentes opciones de las líneas de comentarios. Al realizar el ejercicio que te
proponemos no es necesario que pongas los comentarios del ejemplo.

Los primeros script PHP

Editemos la página anterior (ejemplo6.php) y añadámosle nuestra primera etiqueta PHP guardándola
como ejemplo7.php. Este sería elcódigo fuente:

<html>
<head>
<title>Aprendiendo PHP</title></head>
<body>
Esta es una página 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 código HTML.
Todo lo que aparece en este color son líneas de comentario
de las que hablaremos más 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 -además del texto- un salto de linea HTML.
De este modo, el resultado de cada ECHO
aparecerá en una línea diferente */
# aquí utilizamos solo unas comillas
echo "Este texto solo lleva las comillas de la instrucción<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 opción no podríamos utilizarla
# al revés.
# No podríamos poner \" en las comillas exteriores.
echo "La palabra \"comillas\" usando la barra invertida<br>";
?>
</body>
</html>

Ver ejemplo8.php

Pág. 10
Líneas de comentario

¿Por qué usar líneas de comentario?

A primera vista pueden parecer inútiles. ¿Para qué recargar las páginas con contenidos que no se van a ver ni
ejecutar?. Las líneas de comentario sirven para poder recordar en un futuro qué es lo que hemos hecho al escribir un
script y por qué razón lo hemos hecho así.

A medida que vayamos avanzando verás que en muchos casos tendremos que aplicar estrategias individuales
para resolver cada problema concreto. Cuando necesites hacer una corrección o una modificación al cabo de un tiempo
verás que confiar en la memoria no es una buena opción. Es mucho mejor utilizar una línea de comentario que confiar en
la memoria. ¡Palabra!

Comentarios

Para insertar comentarios en los scripts de PHP podemos optar entre varios métodos y varias posibilidades:

• Una sola linea

Basta colocar los símbolos // al comienzo de la línea o detrás del punto y coma que señala el final de una
instrucción. También se puede usar el símbolo # en cualquiera de las dos posiciones.

• Varias líneas

Si un comentario va a ocupar más de una línea podremos escribir /* al comienzo de la primera de ellas y */ al final
de la última. Las líneas intermedias no requieren de ningún tipo de marca. Los comentarios para los que usemos la forma /*
... */ no pueden anidarse. Si, por error, lo hiciéramos PHP nos dará un mensaje de error.

Ensayando líneas de comentario

En este ejemplo hemos incluido –marcados en rojo– algunos ejemplos de inserción de líneas de comentario.

<html>
<head>
<title>Ejemplo 9</title></head>
<body>
<?php
// Este comentario no se verá en la página

echo "Esto se leerá <BR> "; // Esto no se leerá

/* Este es un comentario de
múltiples líneas 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 */
?>

Pág. 11
</body>
</html>

Ver ejemplo9.php Ver ejemplo10.php

Ejecutemos los dos ejemplos. En el caso del ejemplo9 hemos mantenido el código 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 después de «multilínea con
estos» (marcado en magenta en el código 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 página en blanco. Ello es debido a la configuración por
defecto de la directiva display_errors de php.ini. En este enlace tienes información relativa a la
configuración de las directivas de error.

Pág. 12
Constantes

Definir constantes

Una constante es un valor –un número o una cadena– que no va a ser modificado a lo largo del proceso de
ejecución de los scriptsque contiene un documento. Para mayor comodidad, a cada uno de esos valores se le asigna un
nombre, de modo que cuando vaya a ser utilizado baste con invocar ese nombre.

Cuando ponemos nombre a una constante se dice que definimos esa constante. En PHP las constantes se
definen mediante la siguiente instrucción:

define("nombre","valor");

Dónde 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 numérica que no las requiere.

Los valores asignados a las constantes se mantienen en todo el documento, incluso cuando son invocadas
desde una función.

Si se realizan operaciones aritméticas 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 numéricos, al tratar de operarla aritméticamente PHP
considerará únicamente el valor de los dígitos anteriores a la primera letra o carácter no numérico.

El punto entre caracteres numéricos es considerado como separador de parte decimal.

Tal como puedes ver en el código fuente del ejemplo, es posible definir constantes a las que
se asigne como valor el resultado de una operación aritmética.

Ampliando echo y print

Mediante una sola instrucción echo pueden presentarse de forma simultánea (en la ventana del navegador del
cliente) varias cadenas de caracteres y/o constantes y variables. Basta con ponerlas una a continuación de otra
utilizando una coma como separador.

La forma anterior no es la única –ni la más habitual– de enlazar elementos mediante la instrucción echo. Si en vez
de utilizar la una coma usáramos un un punto (el concatenador de cadenas) conseguiríamos el mismo resultado.

Cuando enlacemos elementos distintos –cadenas, constantes y/o números– hemos de tener muy en cuenta lo
siguiente:

 Cada una de las sucesivas cadenas debe ir encerrada entre sus propias comillas.
 Los nombres de constantes nunca van entre comillas.

Las instrucciones print también permiten concatenar cadenas en una misma instrucción. En este caso solo es
posible usar un puntocomo elemento de unión. Si pusiéramos comas –como podemos hacer con echo– PHP nos daría
un error.

Un ejemplo con constantes

<html><head><title>Constantes</title></head>
<body>
<?php
/* Definiremos la constante EurPta y le asignaremos el valor 166.386 */
define("EurPta",166.386);
/* Definiremos la constante PtaEur asignándole el valor 1/166.386

Pág. 13
En este caso el valor de la constante es el resultado
de la operación aritmética dividir 1 entre 166.386*/
define("PtaEur",1/166.386);
/* Definimos la constante Cadenas y le asignamos el valor:
12Esta constante es una cadena*/
define("Cadena","12Esta constante es una cadena");
/* Definimos la constante Cadena2 y le asignamos el valor:
12.54Constante con punto decimal*/
define("Cadena2","12.54Constante con punto decimal");

/* Comprobemos los valores.


Observa la nueva forma en la que utilizamos echo
Lo hacemos enlazando varias cadenas separadas con
punto y/o coma, según se trate de echo o de print */

echo "Valor de la constante EurPta: ", EurPta, "<BR>";


echo "Valor de la constante PtaEur: ". PtaEur . "<BR>";
print "Valor de la constante Cadena: " . Cadena . "<BR>";
print "Valor de la constante Cadena x EurPta: " . Cadena*EurPta ."<br>";
print "Valor de la constante Cadena2 x EurPta: " . Cadena2*EurPta ."<br>";

echo "Con echo los números no necesitan ir entre comillas: " ,3,"<br>";
print "En el caso de print si son necesarias: " . "7" . "<br>";
print ("incluso entre paréntesis necesitan las comillas: "."45"."<br>");
print "Solo hay una excepción en el caso de print. ";
print "Si los números van en un print independiente no necesitan comillas ";
print 23;

# Pondremos la etiqueta de cierre del script y escribiremos


# una línea de código HTML
?>

<br>Ahora veremos los mismos resultados usando la function prueba<br><br>

<?php

# Estamos dentro de un nuevo script abierto por el <? anterior

/* Aunque aún no la hemos estudiado, escribiremos una función


a la que (tenemos que ponerle siempre un nombre)
vamos a llamar prueba()
Lo señalado 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 función 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 función anterior no se ejecutará hasta que escribamos


una línea –como esta de abajo– en la que ponemos
únicamente el nombre de la función: prueba()
Pág. 14
*/
?>

<?php
prueba();
?>
</body>
</html>

Ver ejemplo11.php

¡Cuidado!

Presta mucha atención a la sintaxis. Olvidar los «;» o no poner unas comillas suelen ser la causa de
muchos mensajes de error.

Pág. 15
Variables

¿Qué es una variable?

Podríamos decir que una variable es el espacio de la memoria RAM del ordenador que se reserva –a lo largo del
tiempo de ejecución de un script– para almacenar un determinado tipo de datos cuyos valores son susceptibles de ser
modificados por medio de las instrucciones contenidas en el propio programa.

En PHP todos los nombres de variable tienen que empezar por el símbolo $.y han de llevar una
letra inmediatamente después del símbolo $ ($pepe1 es un nombre válido, pero $1pepe no lo es).

Para PHP las letras mayúsculas y las minúsculas son distintas. La variable $pepe es distinta de $Pepe.

Definición y tipos de variables

A diferencia de otros lenguajes de programación, PHP no requiere una definición previa de las variables. Se
pueden definen en el momento en que son necesarias y para ello basta que se les asigne un valor por medio de una
expresión como esta:

$variable=valor;

donde valor puede ser una cadena (texto, texto y números, o números que no requieren ser operados
matemáticamente) o sólo unnúmero. En el primero de los casos habría 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 numérico susceptible de ser operado
matemáticamente.

¡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
configuración explicada en páginas anteriores.

El mensaje se debe a la forma en la que está configuradas la directiva relativa a los mensajes de error cuya
explicación puedes ver en este enlace.

Ese mensaje de error puede evitarse de la forma que hemos hecho en el ejemplo14.php o modificando la
directiva error_reporting o display_errors tal como se comenta aquí

Ámbito de las variables

Los valores de una variable definida en cualquier parte de un script –siempre que no sea dentro de una función–
pueden ser utilizados desde cualquier otra parte de ese script, excepto desde dentro de las funciones que contuviera
el propio script o desde las que pudieran estar contenidas en un fichero externo.

Si una variable es definida dentro de una función sólo podrá ser utilizada dentro esa función.

Si en una función aludimos a una variable externa a ella, PHP considerará esa llamada como si la variable tuviera
valor cero (en caso de ser tratada como número) o una cadena vacía ("" es una cadena vacía).

Igual ocurriría si desde fuera de una función hiciéramos alusión a una variable definida en ella.

Si definimos dos variables con el mismo nombre, una dentro de una función y otra fuera, PHP las considerará
distintas. La función utilizará –cuando sea ejecutada– sus propios valores sin que sus resultados modifiquen la
variable externa.

Pág. 16
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 función la siguiente instrucción:

global nombre de la variable;

Por ejemplo: global $a1; permitiría utilizar el valor preexistente de esa variable dentro de una función. Las
eventuales modificaciones que pudiera producirle la función mantendrían su nuevo valor después de finalizar la ejecución
de la función.

En una instrucción global pueden definirse como tales, de forma simultánea, 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 versión 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 automática información muy específica y tienen nombres preasignados que no pueden modificarse.

Las estudiaremos un poco más adelante. Por ahora, sólo citar los nombres de algunas de
ellas: $_SERVER, $_POST, $_GET, $_ENV o$_SESSION son los de algunas de las más importantes.

Practicando con variables y sus ámbitos

El código fuente que ves aquí debajo corresponde al ejemplo12.php. Si pulsas en el enlace que hay debajo y
ejecutas el script verás que aparece un mensaje de error que dice: Notice: Undefined variable: pepe ... que parece
contradictorio con lo afirmado más arriba respecto a que PHP no requiere una definición previa de variables. Esa
afirmación es cierta. Lo que ocurre es que PHP no está dando un mensaje de error propiamente dicho (NOTICE es una
simple advertencia con un significado distinto a ERROR ) sino que advierte de que no se ha hecho algo habitual en una
gran cantidad de lenguajes.

Hay dos formas de evitar ese mensaje. La primera de ellas la comentamos en el propio código fuente sería definir
las variables antes de usarlas (siguiendo la metodología más generalizada de programación). La segunda de las opciones
sería modificar el fichero php.ini cambiando el valor actual: error_reporting = E_ALL | E_STRICT por error_reporting =
E_ALL & ~E_NOTICE. De esta forma, (al anteponer ~aE_NOTICE) estaremos indicando a PHP , tal como explicamos
aquí, que desactive este tipo de mensajes de advertencia.

<html>
<head>
</head>
<body>
<?php
/* En ejemplo12.php la linea siguiente a este comentario($pepe="" )
estará marcada con líneas 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 mayúsculas y minúsculas)


$Pepe="Me llamo Pepe y soy serio y formal";
$Pepa="Me llamo Pepa y también 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 -->

Pág. 17
<?php
echo "<br> El valor de la variable $pepe es: ",$pepe;
echo "<br> No ha puesto nada porque $pepe esta vacía";
echo "<br> El valor de la variable Pepe es: ",$Pepe;
?>

<center><b><br>Invocando la variable desde una función</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 líneas
serán consideradas parte de la función */

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 asignándole un valor nulo tal como puedes ver en la línea
anterior (marcado en rojo) y comentada con //
En el ejemplo14.php hemos descomentar esta línea */
echo "<br> Si invoco la variable Pepe desde una función";
echo "<br>me aparecerá en blanco";
echo "<br>El valor de la variable Pepe es: ",$Pepe;
}
/* esta llave de arriba señala el final de la función.
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 paréntesis */

vervariable();
?>

<!-- mas HTML puro -->


<center><b><br>Ver la variable desde la función
poniendo <i>global</i></b></center>

<?php
# una nueva funcion

function ahorasi(){
# aqui definiremos a $Pepe como global
# la función 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>


Pág. 18
Dentro de la función 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 después de salir de la función
vuelvo al valor original...</center>
<?php
echo "<br>",$Pepa;
?>

</body>
</html>

Ver ejemplo12.php Ver ejemplo13.php Ver ejemplo14.php

Pág. 19
Constantes predefinidas

Constantes predefinidas

PHP dispone de algunas constantes predefinidas que no requieren la instrucción: define("Nombre","Valor") ya que
utilizan palabras reservadas y se asignan valor de forma automática. Algunas de ellas son estas:

__FILE__

Recoge el nombre del fichero que se está ejecutando y la ruta completa de su ubicación en el servidor. Su nombre
lleva dos guiones bajos ( __ ) delante de FILE y otros dos detrás.

__LINE__

Recoge el número de la línea actual (incluidas las líneas en blanco) del fichero PHP cuyos scripts está
interpretando. Puede resultar muy útil para depurar programas.

PHP_OS

Recoge información sobre el sistema operativo que utiliza el servidor en el que se está interpretando el fichero.

PHP_VERSION

Recoge la versión de PHP que está siendo utilizada por el servidor.

¡Cuidado!

Por si existieran dudas –por problemas de visualización– tanto FILE como LINE tienen que llevar dos
guiones bajosdelante y otras dos detrás.

Un ejemplo con constantes predefinidas

<html>
<head>
</head>
<body>
<?php
# La constante del sistema __FILE__ nos devolverá
echo "La ruta completa de este fichero es: ";
echo __FILE__;
# La constante del sistema __LINE__ nos devolverá
# el número de línea que se está interpretando
# también cuenta las líneas en blanco
# cuenta las líneas y verás que devuelve ... 16

echo "<br>Esta es la línea: ",__LINE__, " del fichero";


echo "<br>Estamos utilizando la versión: ",PHP_VERSION, " de PHP";
echo "<br>El PHP se está ejecutando desde el sistema operativo: ",PHP_OS;
?>
</body>
</html>

Ver ejemplo15.php

Pág. 20
Variables predefinidas

Las tablas de valores

En las tablas que hay al final de esta página podrás ver los valores actuales –clasificados por tipos– de algunas
de las variables predefinidas de PHP. Esta información (variables y valores) está siendo extraida de la configuración de
tu servidor y de este documento y se trata de variables de tipo superglobal tal como lo definíamos en este archivo.

Probablemente te extrañará –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, sólo 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
típica de los array.

No vamos a agobiarte con una enumeración de variables y contenidos, pero a poco que observes las tablas de
valores te darás cuenta de que es muy abundante y muy importante la información que recogen. Si analizas las variables
de servidor te darás cuenta de que aparece un montón de información relativa a su configuración: nombre, rutas, nombres
de páginas, IP del servidor, etcétera. Con los demás tipos ocurre algo similar.

Los distintos tipos

Veamos los diferentes tipos de variables predefinidas que existen en PHP. Por ahora, no te preocupes demasiado
sobre la forma de utilizarlas. Las incluimos aquí como una simple enumeración y con una breve descripción de su utilidad.
En temas posteriores haremos referencia a ellas. Por el momento nos bastará con conocer su existencia.

Estamos viendo los valores de las variables de de entorno (ENV) y las de servidor (SERVER), pero, además de
ellas, existen algunas otras cuyos nombres y utilidades vamos a comentarte.

Variables de sesión

Las identificaremos por el nombre $_SESSION.

Este tipo de variables las utilizaremos cuando hagamos mención al uso de sesiones. La utilización de sesiones –
ya abundaremos en ello– es una forma de recoger, de forma temporal en un documento del mismo carácter, información
específica generada a través de los accesos de cada uno de los usuarios. Por ejemplo, cuando accedes a una cuenta de
correo web y escribes tu clave y contraseña se crea un documento temporal en el servidor de correo con un número único
y exclusivo para ese acceso –identificador de sesión– que te permite acceder a diferentes apartados sin necesidad de
que reescribas, en cada una de las páginas, esos mismos valores.

Habrás comprobado también, más de una vez, su carácter efímero cuando al actualizar una página te ha aparecido
ese mensaje típico que dice la sesion ha caducado.

Variables de los métodos GET y POST

Las identificaremos por los nombres $_GET y $_POST

Este tipo de variables –que utilizaremos con frecuencia– recogen la información que se envía desde el cliente para
ser utilizada por el servidor. Recuerda el carácter dinámico de PHP y que ese dinamismo (interacción cliente – servidor)
requiere que el servidor guarde y/o interprete los datos remitidos por el cliente. La existencia de los dos tipos se justifica
porque también existen dos tipos de métodos (maneras) de enviar datos desde el cliente hasta el servidor. Cuando el
método de envío es el llamado GET los datos se recogen en variables de este tipo, y, por el contrario, si ese método envío
fuera POST se recogerían en aquellas.

Variables de transferencia de ficheros

Las identificaremos por el nombre $_FILES. Cuando se trata de la transferencia de un fichero desde
el cliente hasta el servidor –«subir un fichero»– es necesario utilizar un procedimiento de envío distinto de los comentados
en el párrafo anterior. Será en este caso cuando se utilicen variables de este tipo.

Pág. 21
El tipo GLOBALS

A diferencia de las anteriores, las variables de este tipo, $GLOBALS, utilizan una sintaxis algo distinta ya no
llevan el guión bajo detrás de $. Su finalidad es recoger en una tabla los nombres de todas las variables establecidas
como globales –en cada momento– así como sus valores. Si observas la tabla que tienes al final de esta página quizá te
sorprenda leer nombre o página. ¿De donde han salido esos valores?. Bueno... en esta página 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 más 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']
$_SERVER['HTTP_HOST']
$_SERVER['HTTP_CONNECTION']
$_SERVER['HTTP_ACCEPT']
$_SERVER['HTTP_UPGRADE_INSECURE_REQUESTS']
$_SERVER['HTTP_USER_AGENT']
$_SERVER['HTTP_REFERER']
$_SERVER['HTTP_ACCEPT_ENCODING']
$_SERVER['HTTP_ACCEPT_LANGUAGE']
$_SERVER['HTTP_COOKIE']
$_SERVER['PATH']
$_SERVER['SERVER_SIGNATURE']
$_SERVER['SERVER_SOFTWARE']
$_SERVER['SERVER_NAME']
$_SERVER['SERVER_ADDR']
$_SERVER['SERVER_PORT']
$_SERVER['REMOTE_ADDR']
$_SERVER['DOCUMENT_ROOT']
$_SERVER['SERVER_ADMIN']
$_SERVER['SCRIPT_FILENAME']
$_SERVER['REMOTE_PORT']
$_SERVER['GATEWAY_INTERFACE']
$_SERVER['SERVER_PROTOCOL']
$_SERVER['REQUEST_METHOD']
$_SERVER['QUERY_STRING']
$_SERVER['REQUEST_URI']
$_SERVER['SCRIPT_NAME']
$_SERVER['PHP_SELF']
$_SERVER['REQUEST_TIME']
$_SERVER['argv']
$_SERVER['argc']

Variables GLOBALES

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

Pág. 22
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']

Pág. 23
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 50790 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']
/
$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 50790 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']
/
$GLOBALS['HTTP_ENV_VARS']['SHLVL']
1
$GLOBALS['HTTP_ENV_VARS']['RESTARTSRV']
1
$GLOBALS['HTTP_ENV_VARS']['_']

Pág. 24
/usr/local/apache/bin/httpd
$GLOBALS['_COOKIE']['PHPSESSID']
3549ffca60d279286909b5e5c9263df0
$GLOBALS['HTTP_COOKIE_VARS']['PHPSESSID']
3549ffca60d279286909b5e5c9263df0
$GLOBALS['_SERVER']['UNIQUE_ID']
Vg8gNkg0jIEAACEbcYIAAAAa
$GLOBALS['_SERVER']['HTTP_HOST']
www.rinconastur.com
$GLOBALS['_SERVER']['HTTP_CONNECTION']
keep-alive
$GLOBALS['_SERVER']['HTTP_ACCEPT']
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
$GLOBALS['_SERVER']['HTTP_UPGRADE_INSECURE_REQUESTS']
1
$GLOBALS['_SERVER']['HTTP_USER_AGENT']
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101
Safari/537.36
$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_COOKIE']
PHPSESSID=3549ffca60d279286909b5e5c9263df0
$GLOBALS['_SERVER']['PATH']
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['_SERVER']['SERVER_SIGNATURE']

$GLOBALS['_SERVER']['SERVER_SOFTWARE']
Apache/2.2.23 (Unix) mod_ssl/2.2.23 OpenSSL/1.0.0-fips mod_bwlimited/1.4 PHP/5.3.21
$GLOBALS['_SERVER']['SERVER_NAME']
www.rinconastur.com
$GLOBALS['_SERVER']['SERVER_ADDR']
72.52.140.129
$GLOBALS['_SERVER']['SERVER_PORT']
80
$GLOBALS['_SERVER']['REMOTE_ADDR']
190.42.88.89
$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']
26940
$GLOBALS['_SERVER']['GATEWAY_INTERFACE']
CGI/1.1
$GLOBALS['_SERVER']['SERVER_PROTOCOL']

Pág. 25
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']
1443831862
$GLOBALS['_SERVER']['argv']
Array
$GLOBALS['_SERVER']['argc']
0
$GLOBALS['HTTP_SERVER_VARS']['UNIQUE_ID']
Vg8gNkg0jIEAACEbcYIAAAAa
$GLOBALS['HTTP_SERVER_VARS']['HTTP_HOST']
www.rinconastur.com
$GLOBALS['HTTP_SERVER_VARS']['HTTP_CONNECTION']
keep-alive
$GLOBALS['HTTP_SERVER_VARS']['HTTP_ACCEPT']
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
$GLOBALS['HTTP_SERVER_VARS']['HTTP_UPGRADE_INSECURE_REQUESTS']
1
$GLOBALS['HTTP_SERVER_VARS']['HTTP_USER_AGENT']
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101
Safari/537.36
$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_COOKIE']
PHPSESSID=3549ffca60d279286909b5e5c9263df0
$GLOBALS['HTTP_SERVER_VARS']['PATH']
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
$GLOBALS['HTTP_SERVER_VARS']['SERVER_SIGNATURE']

$GLOBALS['HTTP_SERVER_VARS']['SERVER_SOFTWARE']
Apache/2.2.23 (Unix) mod_ssl/2.2.23 OpenSSL/1.0.0-fips mod_bwlimited/1.4 PHP/5.3.21
$GLOBALS['HTTP_SERVER_VARS']['SERVER_NAME']
www.rinconastur.com
$GLOBALS['HTTP_SERVER_VARS']['SERVER_ADDR']
72.52.140.129
$GLOBALS['HTTP_SERVER_VARS']['SERVER_PORT']
80
$GLOBALS['HTTP_SERVER_VARS']['REMOTE_ADDR']

Pág. 26
190.42.88.89
$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']
26940
$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']
1443831862
$GLOBALS['HTTP_SERVER_VARS']['argv']
Array
$GLOBALS['HTTP_SERVER_VARS']['argc']
0
$GLOBALS['_REQUEST']['PHPSESSID']
3549ffca60d279286909b5e5c9263df0
$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']

Pág. 27
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']
3549ffca60d279286909b5e5c9263df0
$GLOBALS['nombre2']
PHPSESSID

Pág. 28
Otras variables

Valores de las variables

Cuando hablábamos de las variables y nos referíamos a su ámbito decíamos que las variables definidas dentro
de una función pierden sus valores en el momento en el que abandonemos el ámbito de esa función, es decir,
cuando finaliza su ejecución.

Decíamos también que si el ámbito en el que hubiera sido definida fuera externo a una función los valores sólo se
perderían–temporalmente– mientras durara la eventual ejecución de las instrucciones de aquella y que, una vez acabado
ese proceso, volvían a recuperar sus valores.

Bajo estas condiciones, si invocáramos repetidamente la misma función obtendríamos cada vez el mismo
resultado porque las posibles modificaciones que pudieran haberse producido (a través de las instrucciones contenidas
en la función) en sus valores se perderían cada vez que abandonáramos la función con lo cual, cada una de
las llamadas sucesivas restablecería el valor inicial.

Variables estáticas

Para poder conservar el último valor de una variable definida dentro de una función basta con definirla
como estática. La instrucción que permite establecer una variable como estática es la siguiente:

static nombre = valor;

Por ejemplo: si la variable fuera $a y el valor inicial asignado fuera 3 escribiríamos: static $a=3;

La variable conservará el último de los valores que pudo habérsele asignado durante la ejecución de
la función que la contiene. No retomará el valor inicial hasta que se actualice la página.

Ejemplo de variables estáticas

<?php
# Observa que hemos prescindido de los encabezados HTML.
# No son imprescindibles para la ejecución de los scripts
/* Escribamos una función y llamémosla sinEstaticas
Definamos en ella dos variables sin ninguna otra especificación
e insertemos las instrucciones para que al ejecutarse
se escriban los valores de esas variables */

function sinEstaticas(){

# Pongamos aquí sus valores iniciales


$a=0;
$b=0;

# Imprimamos estos valores iniciales

echo "Valor inicial de $a: ",$a,"<br>";


echo "Valor inicial de $b: ",$b,"<br>";

/* Modifiquemos esos valores sumando 5 al valor de $a


y restando 7 al valor de $b.
$a +=5 y $b -=7 serán quienes haga esas
nuevas asignaciones de valor
ya lo iremos viendo, no te preocupes */

$a +=5;
$b -=7;

Pág. 29
# 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 función con una modificación que será
# asignar la condición de estática a la variable $b
# Llamemos a esa función: conEstaticas

function conEstaticas(){

# Definimos $b como estática


$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 ejecución

print ("Esta es la primera llamada a sinEstaticas()<br>");

# Invoquemos la función sinEstaticas;

sinEstaticas();
# Añadamos 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 función 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

Además del método habitual de asignación 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 sería esta:

Pág. 30
$$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),
habríamos de poner algo como esto:

$$color="es horrible";

Si se tratara de visualizar el valor de esta nueva variable podríamos hacerlo de una de estas tres maneras:

print $$color; o print ${$color}; o también print $verde;

Cualquiera de las instrucciones anteriores nos produciría la misma salida: es horrible. Podemos preguntarnos
¿cómo se justifica que existan dos sintaxis tan similares como $$color y ${$color}? ¿Qué pintan las llaves?.

La utilización de las llaves es una forma de evitar situaciones de interpretación confusa. Supongamos que las
variables tienen un nombre un poco más raro. Por ejemplo que $color no se llama así sino $color[3] (podría 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] cabría la duda de si el número 3 pertenece (es un índice) a la
variable $color o si ese número corresponde a $$color. Con print ${$color[3]} no habría lugar para esas dudas. Estaríamos
aludiendo de forma inequívoca a 3 como índice de la variable $color.

¿Qué ocurre cuando la variable previa cambia de valor?

Cuando la variable utilizada para definir una variable de variable cambia de valor no se modifica ni el nombre de
esta última ni tampoco su valor. Puedes ver este concepto, con un poco más de detalle, en el código fuente del ejemplo.

<?php
# Definamos una variable y asignémosle 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 los contenidos de esas variables


print ( "El color ".$color. $$color ."<br>");
#o también
print ( "El color ".$color. ${$color}."<br>");
# o también
print ( "El color ".$color. $rojo."<br>");

# advirtamos lo que va a ocurrir al visualizar la página

print ("Las tres líneas 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 automáticamente variables
que tengan por nombre el nuevo valor de $color */

Pág. 31
# 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 ("detrás 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 símbolo @
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" aún 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 ejemplo18.php
Con mensaje de error Sin mensajes de error

Inserción de símbolos como elementos de texto

Tanto PHP como los navegadores hacen interpretaciones como símbolos del lenguaje de algunos caracteres
especiales tales como $,", o <, que cuando se pretendieran incluir como elementos no se visualizarían en pantalla.

Cuando pretendamos que aparezcan escritos tendremos que indicarlo de una forma especial. En este
enlace podrás ver la forma de hacerlo.

Pág. 32
Tipos de variables

Tipos de variables

Ya hemos comentado que en PHP no es necesaria una definición previa del tipo de variables. Según los valores
que se les vayan asignando, las variables podrán cambiar de tipo –de modo automático– y se irán adaptando a los valores
que contengan en cada momento.

Las variables en PHP pueden ser de tres tipos:

 Enteras (tipo Integer)


 De coma flotante (tipo Double)
 Cadenas (tipo String)

Cualquier número entero cuyo valor esté comprendido entre ± 231 será interpretado por PHP como de tipo Integer.

Si el valor de una variable es un número decimal o –siendo entero– desborda el intervalo anterior, bien por
asignación directa o como resultado de una operación aritmética, 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 números
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 máximo Valor mínimo Observaciones
Cualquier valor numérico entero (dentro de este
Integer $a=1234 2147483647 -2147483647 intervalo) que se asigne a una variable será
convertido a este tipo
Cualquier valor numérico decimal, o entero fuera del intervalo anterior, que se asigne a
Double $a=1.23 una variable la convertirá a este tipo
Cualquier valor entrecomillado (sean números o letras) que se asigne a una variable la
String $a="123" convertirá a este tipo

Determinación de tipos de variables

PHP dispone de la función:

gettype(variable)

dónde variable es el nombre de la variable, devuelve una cadena de caracteres indicando el tipo de la variable
que contiene.La cadena devuelta por esta función puede ser: Integer, double o string.

Dado que PHP gestiona las variables de forma automática y modifica los tipos de acuerdo con los valores que va
tomando durante la ejecución del script, este valor puede ser distinto según el punto del script dónde se ejecute la función.

En esta tabla tienes algunos ejemplos de aplicación de esa función. Puedes observar –en la columna Sintaxis– que
para visualizar el resultado anteponemos echo a gettype. Es decir, le indicamos a PHP que muestre el resultado obtenido
al determinar el tipo de variable.

Ejemplos de determinación del tipo de una variable


Variable Sintaxis Devuelve
$a1=347 echo gettype($a1) integer
$a2=2147483647 echo gettype($a2) integer
$a3=-2147483647 echo gettype($a3) integer

Pág. 33
$a4=23.7678 echo gettype($a4) double
$a5=3.1416 echo gettype($a5) double
$a6="347" echo gettype($a6) string
$a7="3.1416" echo gettype($a7) string
$a8="Solo literal" echo gettype($a8) string
$a9="12.3 Literal con número" echo gettype($a9) string
$a10="" echo gettype($a10) string

Forzado de tipos de variable

PHP permite forzar los tipos de las variables. Eso quiere decir que se puede obligar a PHP a asignar un tipo
determinado a una variable determinada, siempre que los valores que contenga estén dentro del rango del nuevo tipo
de variable.

Los tipos se pueden forzar tanto en el momento de definir la variable como en un momento posterior.

Forzado y asignación simultánea de valores

Al asignar un valor a una variable, se puede forzar su tipo de la siguiente forma. Si deseamos que la variable pase
a ser tipo de doublebasta con anteponer a su valor –entre paréntesis– tal como se indica una de las expresiones
siguientes:

(double), (real) o (float).

Por ejemplo, tanto con $a=((double)45); como con $a=((float)45); o con $a=((real)45); se produciría el mismo
resultado: convertir la variable $a a tipo Double.

Para forzar una variable a tipo Integer podemos anteponer a su valor una de estas expresiones:

(integer), o (int).

Por ejemplo: $b=((integer)4.5); o $b=((int)45); producirían el mismo efecto: convertir la variable $b a tipo Integer.

Para forzar una variable a tipo String basta con anteponer a su valor (entre paréntesis):

(string).

Por ejemplo: $c=((string)4.5); convertiría la variable $c a tipo String.

Forzado de tipo de variable


Variable Sintaxis Devuelve
$a1=347 echo gettype((real)$a1) double
$a2=2147483647 echo gettype((double)$a2) double
$a3=-2147483647 echo gettype((float)$a3) double
$a4=23.7678 echo gettype((int)$a4) integer
$a5=3.1416 echo gettype((integer)$a5) integer
$a6="347" echo gettype((double)$a6) double
$a7="3.1416" echo gettype((int)$a7) integer
$a7="3.1416" echo gettype((string)$a7) string
$a8="Solo literal" echo gettype((double)$a8) double
$a9="12.3 Literal con número" echo gettype((int)$a9) integer

Pág. 34
¡Cuidado!

Al modificar los tipos de variables pueden modificarse sus valores.


Si forzamos a entera una variable que contenga un número decimal se perdería la parte decimal y la
variable modificada solo contendría el valor de la parte entera.
Si tratamos de convertir a numérica una variable alfanumérica el nuevo valor sería cero.

Nuevos valores de la variable


Valor inicial Sintaxis Nuevo valor
$a1=347 echo ((real)$a1) 347
$a2=2147483647 echo ((double)$a2) 2147483647
$a3=-2147483647 echo ((float)$a3) -2147483647
$a4=23.7678 echo ((integer)$a5) 23
$a5="3.1416" echo ((double)$a6) 3.1416
$a6="347" echo ((int)$a7) 347
$a7="3.1416" echo ((string)$a7) 3.1416
$a8="Solo literal" echo ((int)$a8) 0
$a9="12.3 Literal con número" echo ((double)$a9) 12.3
$a9="12.3 Literal con número" echo ((int)$a9) 12
$a10="" echo ((int)$a10) 0

Forzado de tipos en variables ya definidas

La forma más aconsejable de forzado de tipos en variables que ya estuvieran definidas previamente, es el uso de
la siguiente instrucción:

settype( var, tipo)

donde var es el nombre de la variable cuyo tipo pretendemos modificar y tipo una expresión que puede contener
(entre comillas) uno de estos valores: 'double', 'integer', o 'string' según se trate de forzar a: coma flotante, entero,
o cadena.

Un ejemplo podría ser este: settype($a,'integer') que convertiría a tipo entero la variable $a.

La ejecución de la instrucción settype devuelve (da como resultado) un valor que puede ser: true o false (1 ó 0)
según la conversión se haya realizado con éxito o no haya podido realizarse.

Aquí tienes algunos ejemplos del uso de esa función. La tabla está organizada en bloques de tres filas que
corresponden a la ejecución de tres instrucciones y a la visualización del resultado de cada una de ellas.

El resultado de settype –primera fila– solo podrá ser 1 ó 0 según la instrucción se haya ejecutado con éxito o no
haya podido realizarse.

En la segunda fila comprobamos el nuevo tipo de variable obtenida mediante la ejecución de la instrucción anterior
y en la terceravisualizamos los nuevos valores de la variable, que pueden haber cambiado como consecuencia del cambio
de tipo.

Forzado de tipos con settype()


Variable Sintaxis Devuelve
echo (settype($a1,'double') 1
$a1=347 echo gettype($a1) double
echo $a1 347
$a2=2147483647 echo (settype($a2,'double') 1

Pág. 35
echo gettype($a2) double
echo $a2 2147483647
echo settype($a3,'double') 1
$a3=-2147483647 echo gettype($a3) double
echo $a3 -2147483647
echo settype($a4,'integer') 1
$a4=23.7678 echo gettype($a4) integer
echo $a4 23
echo settype($a5,'integer') 1
$a5=3.1416 echo gettype($a5) integer
echo $a5 3
echo settype($a6,'double') 1
$a6="347" echo gettype($a6) double
echo $a6 347
echo settype($a7,'integer') 1
$a7="3.1416" echo gettype($a7) integer
echo $a1 3
echo settype($a8,'double') 1
$a8="Solo literal" echo gettype($a8) double
echo $a8 0
echo settype($a9,'integer') 1
$a9="12.3 Literal con número" echo gettype($a9) integer
echo $a9 12

Operaciones con distintos tipos de variables

PHP permite la realización de operaciones aritméticas con cualquiera de los tres tipos de variables y adecúa el
resultado al tipo más apropiado.

En la tabla puedes ver algunos ejemplos, pero, en resumen, ocurre lo siguiente:

 Al operar con dos enteros, si el resultado está dentro del rango de los enteros, devuelve un entero.
 Si al operar con dos enteros el resultado desborda el rango entero, convierte su valor, de forma automática, al
tipo coma flotante
 Al operar un entero con una variable tipo coma flotante el resultado es de coma flotante.
 Al operar con una cadena lo hace como si se tratara de un entero. Si hay caracteres numéricos al comienzo, los
extrae (hasta que aparezca un punto o un carácter no numérico) y los opera como un número entero.
 Si una cadena no comienza por un carácter numérico PHP la operará tomando su valor numérico como CERO.
La tabla siguiente contiene –en cada fila– los valores asignados a dos variables (A y B) y el resultado de la suma de
ambas. A continuación se recogen los tipos de variable de cada una de ellas y el del resultado. El tipo de este último –
generado por PHP– estará condicionado por el valor del resultado de cada una de las operaciones.

Resultados de operaciones y tipos de variables resultantes


Valores Tipos de variables
A B A+B A B A+B
12 16 28 integer integer integer
12 2147483647 2147483659 integer integer integer
-12 -2147483640 -2147483652 integer integer integer
12 1.2456 13.2456 integer double double
1.2456 12 13.2456 double integer double

Pág. 36
1.2456 123.4567 124.7023 double double double
12 abc 12 integer string integer
1.2456 abc 1.2456 double string double
12 12abc 24 integer string integer
12 12.34567abc 24.34567 integer string double
1.2456 12.34567abc 13.59127 double string double
1.2456 12.3e2abc 1231.2456 double string double
abc 12abc 12 string string integer
abc 12.34567abc 12.34567 string string double
12abc 12.34567abc 24.34567 string string double

Pág. 37
Utilizando formularios

PHP dinámico

Hasta el momento, PHP sólo nos ha servido para escribir una serie de scripts y ver los resultados de su ejecución
pero aún no hemos hecho mención alguna a la manera en la que puede establecerse un diálogo (interacción)
entre cliente y el servidor que, en definitiva, es la razón de ser de las páginas dinámicas.

Cuando se trata de páginas estáticas la comunicación está muy restringida. El cliente hace una petición (escribe
el nombre de una página en la barra de direcciones del navegador) y el servidor se limita a devolver los contenidos de
esa página. Un primer paso para mejorar es esa comunicación será que el cliente especifique algo más en su petición y
que el servidor interprete esa información complementaria. Ese algo más puede incluirse en la barra de direcciones con
la siguiente sintaxis:

pagina.php?nombre1=valor1&nombre2=valor2, ...

Dónde pagina.php es la dirección de una página que contiene scripts PHP y dónde ? es un carácter obligatorio
que indica que detrás de él se incluye más información. Esa información estará formada por parejas nombre -
valor enlazadas por un signo = y separadas entre sí por el símbolo &.

De esa forma el servidor entendería la petición de la siguiente forma: Vete a la página pagina.php, mira los scripts
PHP, asigna a las variables nombre1, nombre2 etcétera los valores valor1, valor2,... ejecuta los scripts con esos valores
y devuélveme los resultados.

Observarás que los nombres de las variables nunca llevan el signo $ y que los valores de las variables –sean
números o cadenas–tampoco se escriben nunca entre comillas.

Algunos caracteres especiales (& por ejemplo) no pueden escribirse directamente dado que se prestan a confusión
dando lugar a la duda de si habrían de intepretarse como un valor como el símbolo de unión. En esos casos es
necesario sustituir el carácter por su codificación URL que representa cada carácter anteponiendo el signo % al valor
de su código ASCII expresando en formato hexadecimal.

Se pueden incluir tantos nombre = valor como se desee. La única restricción es la longitud máxima permitida por
el método GET (el utilizado en este caso) que se sitúa en torno a los 2.000 caracteres.

Recepción de datos

Cuando es recibida por el servidor la petición de un documento con extensión .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 automática, en variables predefinidas de dos tipos:

$_GET['nombre1']=valor1, $_GET['nombre2']=valor1, etcétera, en las que nombre1, nombre2, ...


coinciden exactamente con nombres especificados en las petición y los valores asignados a estas variables también
coinciden con los recibidos, junto con cada nombre, a través de la petición.

$_REQUEST['nombre1']=valor1, $_REQUEST['nombre2']=valor1 recoge los mismos valores que la


anterior $_GET. Esta aparente duplicidad de información tiene una funcionalidad añadida que veremos un poco más
adelante

La variables anteriores tienen una sintaxis un poco engorrosa. Por eso, las versiones más recientes de PHP
incluyen una nueva función que puede agregar algo de funcionalidad. Es la siguiente:

extract(array asociativo)

que crea de forma automática 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 función extract($_GET) PHP creará de forma automática las variables $nombre1=7 y $nombre2='pepe'.

Pág. 38
Mediante extract($_REQUEST) obtendrían los mismos resultados. En definitiva, la función extract() no hace otra
cosa que crear variables PHP con idéntico nombre al indicado en la petición.

Hay configuraciones de PHP en las que no es necesario utilizar la función extract(). Cuando el fichero php.ini tiene
configurada la directiva register_globals=ON las variables del tipo: $nombre1=valor1, $nombre2=valor2, etcétera se
crearían de forma automática al ser recibida la petición del cliente.

¡Cuidado!

La directiva register_globals ha evolucionado mucho a través de las distintas versiones de PHP. En las
versiones más antiguas venía configurada, por defecto, con el valor ON. Actualmente viene configurada,
también por defecto como OFF y se comenta que en futuras versiones de PHP su valor seguirá
siendo OFF pero ya no será posible modificarla.
Por ello, quizá lo más prudente escribir nuestro código pensando siempre que su configuración es OFF y
además es inmodificable.

Veamos algunos ejemplos.

<?php
/* Empezaremos utilizando
$_GET['a'], $_GET['b' */
# Pongamos un comentario de advertencia. Recuerda que <br>
# sirve para insertar un salto de línea 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 también 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 verás que te aparece una retahila de mensajes de advertencia. Es lógico 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 gestión de errores de forma muy estricta nos advierte que esas variables no
han sido inicializadas.

Si escribieras ejemplo19.php?a=21&b=456 todo funcionaría correctamente. No habría lugar al mensaje de


advertencia porque las variables ya tienen contenido.

Para evitar la visualización de los mensajes de advertencia existen diferentes posibilidades. Además de las
mencionadades cuando estudiábamos las variables –las tienes comentadas en este enlace– tenemos la opción 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 símbolo @. Mediante ese símbolo (@) inhibimos la aparición del mensaje de error
al ejecutarse la instrucción a la que precede. Eso es lo que hemos hecho en el ejemplo20. Verás que al ejecutarlo ya no
aparece el mensaje de error.

Como es lógico, al asignar valores a las variables escribiendo en la barra de direcciones del navegador la siguiente
dirección: ejemplo20.php?a=21&b=456, (o pulsemos directamente en este enlace) el resultado no diferiría en nada del
obtenido con el ejemplo19.

¡Cuidado!

Aquí, más que nunca, conviene reiterar, una vez más, los errores de sintaxis más frecuentes:
 Los nombres de variables son distintos si se cambian mayúsculas y minúsculas. Pon mucho cuidado
en escribirlos correctamente.
 Los nombres de las variables predefinidas, tales como $_GET, etcétera van en mayúsculas.
Pág. 39
 No olvides poner punto y coma al final de cada línea de instrucciones.
 Presta atención a la apertura/cierre de comillas y mucha más atención aún 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 función extract para leer los datos recibidos.

<?php
/* al incluir extract se crearán variables automáticas
con los nombres incluidos a través de la barra de direcciones
del navegador */
extract($_GET);
/* Escribamos una instrucción, que imprima en pantalla
el valor de una de las variables extraidas ($a),
una "x" que hará funciones de aspa
en la presentación, 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);
# Añadamos una bobadilla, para animar... ;-)
print ("<br> ¡¡Acabamos de usar la función extract!!");
?>

ejemplo21.php ejemplo22.php

Ejecuta este ejemplo (no aparecerán mensajes de advertencia porque hemos incluido los @ que los inhiben) y
observa lo que aparece. ¿Sólo x =0? ¿y la otra línea?

El resultado es lógico. 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 vacía 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 dirección: ejemplo21.php?a=13&b=7, (también puedes pulsar en este enlace) y podremos
comprobar que 13 x 7 = 91 . Observa también que ahora no aparece ningún mensaje de error porque hemos
antepuesto @ a la instrucción 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 pero tiene una diferencia importante. Hemos comentado la línea
que contiene la función 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 requería que la
directiva register_globals de php.ini estuviera ON y, por defecto, esta directiva viene configurada
comoregister_globals=Off.

Si pruebas a cambiar esa configuración, reinicias el servidor y pulsas de nuevo en el enlace, verás que esta vez
si ha recibido los valores de a y b y nos ha dado el resultado de la operación.

¡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 páginas utilizando un hosting ajeno debes usar la opción de mayor
compatibilidad se son, sin duda alguna, $_GET, ó $_REQUEST complementadas, si lo estimas más
cómodo con la función 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 código fuente para adecuarlo a la configuración de tu hosting.

Pág. 40
Envío a través de formularios

La interacción cliente–servidor que acabamos de ver resulta incómoda en su uso y no demasiado estética.

Hay una segunda opción –la de uso más frecuente– que es la utilización de formularios que no son elementos
propios de PHP –actúan del lado del cliente– siendo su estudio es más propio del ámbito de HTML que de PHP. No
obstante –por si te fuera necesario– aquí tienes un formulario, en el que se comenta la sintaxis de sus elementos más
comunes.

Un ejemplo formulario

<html>
<head>
</head>
<body>
<!-- Un formulario debe empezar siempre con una etiqueta de este tipo <form ...>
dentro de la cual obligatorio indicar con esta sintaxis
action='nombre.extension'
el nombre de la página destinataria de la información 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 petición)

Es opcional incluir (también 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'

También 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 alfabéticos, sin tildes ni eñes y sin espacios. Salvo
excepciones que veremos
más adelante el nombre ha de ser único y distinto para cada elemento del
formulario.

También 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.
También puede conteenr (es opcional) size=xx. Su utilidad es la de
ajustar el
tamaño de la ventana al número de caracteres que se indiquen mediante
xx //-->

<input type='text' name='nombre' value='' size=15><br>


Escribe tu clave:
Pág. 41
<!-- <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 opción– deben tener el
mismo nombre (name)
value='xxxxx' deberá tener un valor distinto en cada uno de ellos.
El valor (loquesea) de la opción marcada es que será transferido a través
del formulario
Si queremos que una opción 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 descripción de los valores después de cerrar la etiqueta de cada uno de
esos input.
Al enviar el formulario solo se transmite el value de la opción
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 serán transferidos a través 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 descripción de los valores después 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 máximo que estarías 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 después de opción en la
seleccionada
salvo que dentro de la propia etiqueta opción se incluya un value.
Si dentro de una etiqueta option escribimos selected será esa la que aparezca
seleccionada
,por defecto, al cargarse el formulario//-->

Pág. 42
<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>Más 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
número de filas)
cols=yy (indicará el ancho expresado en número 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 iría oculto'><br>

<!-- El <input type='submit'> es el encargado de ejecutar la action incluida en


la etiqueta
de apertura del formulario. Sería la llamada a la página que se indica en
la action
El texto que se incluya en su value será el que se visualice en el propio
botón 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>

Interpretación de los datos recibidos a través de formularios

Igual que ocurría en el caso anterior, los datos enviados a través de un formulario son recogidos en diferentes
tipos de variables predefinidas. Ahora se añade una nueva particularidad. Existe la posibilidad de dos métodos (method)
de envío: GET o POST. En el caso anterior decíamos que se utilizaba el método GET, pero en el caso de los formularios
son posibles ambos métodos. Conviene tenerlo en cuenta.

Método GET

No se diferencia en nada de lo descrito para el supuesto anterior. Utiliza las mismas variables predefinidas
($_GET y $_REQUEST), las utiliza con idéntica sintaxis y se comporta de igual forma en lo relativo a las opciones
de register_globals.

Pág. 43
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 serían los siguientes. En los casos de campos
tipo: text, password y textarea serían 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– recogería el valor
indicado en la casilla marcada; mientras que si se trata de campos tipo checkbox se transferirían únicamente las variables
–y los valores– que corresponden a las casillas marcadas.

Si se tratara de un campo oculto –tipo hidden– se transferiría el valor contenido en su etiqueta y, por último, en el
caso del select sería transferido como valor de la variable la parte del formulario contenida entre las etiquetas
<option></option> de la opción seleccionada salvo que, dentro de la propia etiqueta option se incluya un valor
mediante value=xxxxx.

Método POST

En el caso de que el método de envío sea POST hay una diferencia a tener en cuenta en cuanto a las variables
que recogen la información. Ahora será la variable superglobal $_POST['nombre'] la que reemplace
a $_GET['nombre'] usado en el caso del método GET.

Si register_globals está en On el comportamiento de las variables directas es idéntico al comentado para el caso
de GET.

La opción REQUEST

La variable superglobal $_REQUEST['nombre'] aúna las funcionalidades de $_GET y $_POST y que recoge tanto
los valores transferidos mediante el método GET como mediante POST.

Identificación del método de envío

PHP recoge en una variable el método utilizado para enviar los datos desde un formulario. Se trata de la variable:

$_SERVER['REQUEST_METHOD']

que devuelve una cadena (GET ó POST) que especifica el método de envío utilizado.

Diferencias ente los métodos GET y POST

Las diferencias entre uno y otro método son las siguientes:

Método GET

 – Al ser enviado el formulario se carga en el navegador la dirección especificada como action, se le añade un ? y a
continuación se incluyen los datos del formulario. Todos los datos de la petición van a ser visibles en la barra de
direcciones del navegador.
 – Únicamente son aceptados los caracteres ASCII.
 – Tiene una limitación en el tamaño máximo de la cadena que contiene los datos a transferir. En IE esa limitación es de
2.083 caracteres.
 – Suele ser utilizado cuando los datos no producen modificaciones en el servidor tal como ocurre en consultas en bases
de datos, búsquedas y similares.
Método POST

 – No tiene las limitaciones indicadas para el caso de GET en lo relativo a la aceptación de caracteres no ASCII.
 – Los datos del formulario no se visualizan en la barra de direcciones del navegador.
 – Este método de transferencia de datos es el más habitual cuando se utilizan formularios.

Pág. 44
 – Suele ser utilizado cuando los datos transferidos producen algún tipo de modificación en los dos datos almacenados en
el servidor tales como: altas en bases de datos, modificaciones, etcétera.

Tipos de contenidos de los formularios

Vamos a contemplar un último aspecto relativo a los formularios. Se trata de la forma de codificar los datos para
su transmisión (ENCTYPE). Puede especificarse dentro de la etiqueta<form> utilizando la sintaxis: enctype='valor'.

En el caso de que no se especifique, tomará el valor application / x-www-form-urlencoded, sea GET o POST el
método que se utilice.

ENCTYPE admite también el valor multipart/form-data como una opción alternativa a la anterior.

Las diferencias básicas entre ambos modos de codificación son las siguientes:

 – En el tipo application/x-www-form-urlencoded los nombres de control y los valores se transforman en secuencias de


escape, es decir, convirtiendo cada byte en una cadena %HH, donde HH es la notación hexadecimal del valor del byte.
 – Además, los espacios son convertidos en signos +, los saltos de línea se representan como %0D%0A, el nombre y el
valor se separan con el signo = y los diferentes bloques nombre/valor, se separan con el carácter &.
 – El tipo de contenido application / x-www-form-urlencoded es utilizable cuando el volumen de datos es reducido y todos
los caracteres remitidos son ASCII.
 –En cuanto a la encriptación tipo multipart/form-data, sigue las reglas de las transferencias MIME, que comentaremos
más adelante cuando tratemos el tema del correo electrónico.
 – 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 vacía ("") como valor de action en un formulario se recargará el mismo
documento como respuesta al envío del formulario.

Ejemplos de las diferentes opciones de formularios

Intentaremos ver ejemplos de las diferentes opciones. Utilizaremos un formulario idéntico al descrito anteriormente
dónde incluiremos como action una llamada al script ejemplo26.php (su código fuente es el que puedes ver aquí debajo)
y donde dónde no especificaremos ningún valor para ENCTYPE con lo cual asumirá su valor por defecto, application / x-
www-form-urlencoded

En el código fuente que ves aquí debajo intentamos leer los contenidos transferidos utilizando las diferentes
posibilidades que nos ofrece PHP. Incluimos dos ejemplos cuya una única diferencia el método utilizando en el formulario.
En el primero de ellos se utiliza el método GET y en el segundo POST.

<?php
print "Empezaremos comprobando el método de envío";
print " El method que ha usado fué: ".$_SERVER['REQUEST_METHOD']."<br>";
print "Leeremos los contenidos de la superglobal \$_REQUEST";
print " Funcionará tanto con el método 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 " Sólo dará resultados cuando el método sea POST"."<br>";
Pág. 45
@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 " Sólo dará resultados cuando el método 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 " Sólo 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 función extract aplicada a \$_REQUEST";
print " de esa forma dará resultados tanto cuando el método sea GET como cuando
sea POST. ";
print " Si la hubiéramos aplicado \$_POST solo funcionaría con ese método.";
print " Si lo hubiéramos hecho \$_GET solo atendería ese método"."<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 opciónENCTYPE="multipart/form-data" manteniendo el resto del formulario sin ninguna modificación.

«Con method = POST» «Con method = GET»

La seguridad en los envíos de datos

El tema de la seguridad es una preocupación constante entre los usuarios de Internet. Cuando utilizamos las
técnicas que venimos comentando en esta página –nos referimos siempre al caso de servidores remotos– corremos dos
tipos de riesgo de seguridad que no estaría de más tener en cuenta.

Pág. 46
El riesgo de que la información sea interceptada durante el proceso de transmisión desde el cliente hasta el
servidor lo compartimos con todos los demás usuarios de la Red, pero hay otro –el riesgo de daños en los contenidos de
nuestro espacio de servidor– que esexclusivamente nuestro.

La transparencia del método GET es tal, que incluso muestra –en el momento del envio– todos los datos en la
barra de direcciones del navegador. Eso permite que cualquier usuario pueda conocer a simple vista la ruta completa
hasta el script, así como los nombres y valores de las variables.

Cuando se usa el método POST los formularios son un poco más discretos, pero igual de transparentes.
El código de cualquier formulario estará accesible sólo con ir a la opción Ver código fuente y allí estarán de nuevo todos
los datos: nombre del script, nombres de las variables, etcétera, con lo que, cualquier usuario y desde cualquier sitio,
puede acceder a ese script.

No haría falta ni usar nuestro formulario. Bastaría guardar una copia del mismo en el ordenador del visitante y
después –haciendo ligerísimos retoques– se podría acceder a nuestro script sin necesidad de utilizar el formulario alojado
en nuestro servidor.

Si pensamos que uno de nuestros scripts puede estar diseñado con el fin de modificar algunos de los contenidos
de nuestro espacio –borrar datos, por ejemplo– seguramente sería cuestión de empezar a preocuparnos, y mucho más
si en nuestro servidor tenemos datosimportantes.

Existen formas de evitar, o al menos reducir, este tipo de riesgos. Restringir a usuarios autorizados el uso de
algunos subdirectorios es una de ellas, almacenar datos importantes fuera del directorio root del servidor es otra y el uso
de algunas de las variables predefinidas como elementos de protección puede ser una tercera.

Hacemos este comentario a título meramente informativo. Por el momento nos basta con manejar los formularios,
pero queremos que tengas presente la existencia de ese tipo de riesgos. Más adelante, ve- remos la manera de tratar de
evitarlos. En los contenidos opcionales de estos materiales hemos incluido información relativa a la configuración y uso
de servidores seguros que pueden paliar en gran medida algunos de estos riesgos de seguridad.

Pág. 47
Operaciones aritméticas

Operaciones aritméticas

En páginas anteriores hemos podido ver que PHP permite utilizar un tipo de variables –las numéricas– cuyos
valores puedan seroperados de la misma forma que se hace con los números en la vida cotidiana.

Los resultados de las operaciones pueden utilizarse de forma directa o ser recogidos en una nueva variable. Si
asignamos a una nueva variable el resultado de una operación el valor contenido en ella no se modifica si
cambian posteriormente los de las variables que intervinieron su creación.

Sintaxis de print y echo

Si queremos encadenar en una sola instrucción –echo ó print– el resultado de una operación junto con otras
variables (o cadenas) esimprescindible poner entre paréntesis las instrucciones de la operación. Esta norma solo tiene
dos excepciones: en caso de que el print solo contenga la propia operación o cuando utilicemos echo y el separador sea
una coma.

Operadores aritméticos

Las diferentes operaciones aritméticas se realizan en PHP utilizando la siguiente sintaxis:

$a + $b

Devuelve la suma de los valores númericos contenidos en las variables $a y $b.

$a – $b

Devuelve la diferencia de los valores númericos contenidos en las variables $a y $b.

$a * $b

Devuelve el producto de los valores númericos contenidos en las variables $a y $b.

$a / $b

Devuelve el cociente de los valores númericos contenidos en las variables $a y $b.

(int)($a / $b)

Devuelve el cociente entero de los valores númericos contenidos en las variables $a y $b.

$a % $b

Devuelve el resto de la división entera de los valores númericos contenidos en las variables $a y $b.

Sqrt($a)

Devuelve la raíz cuadrada del valor númerico contenido en la variables $a.

Pág. 48
pow($a,$b)

Devuelve el resultado de elevar el valor númericos contenido en la variable $a a la potencia indicada en la variable
$b (ab)

pow($a,1/$b)

Devuelve el resultado de elevar el valor númericos contenido en la variable $a a la potencia indicada en la


variable 1/$b lo cual no es otra cosa que la raíz de índice $b de $a.

Abs($a);

Devuelve el valor absoluto del valor númerico contenido en la variable $a.

<?php
# definamos dos variables numéricas 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 operación 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 paréntesis 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 multiplicación antes que la suma
print "<br>No he puesto paréntesis y el resultado es: ".($a+$b*$c);
# Si escribimos print(($a+$b)*$c) nos hará la suma y luego multiplicará
print "<br>He puesto paréntesis y el resultado es: ".(($a+$b)*$c);
?>

ejemplo33.php

Operaciones aritméticas
Operación Sintaxis A B Resultado
Suma $a+$b 12 -7.3 4.7
Diferencia $a-$b 12 -7.3 19.3
Producto $a*$b 12 -7.3 -87.6

Pág. 49
Cociente $a/$b 12 -7.3 -1.64383561644
Cociente entero (int)($a/$b) 12 -7.3 -1
Resto de la división $a%$b 12 5 2
b
Potencias a pow($a,$b) 12 5 248832
b
Potencias a pow($a,$b) -7.3 -3 -0.00257058174836
Raíz cuadrada Sqrt($a) 12 3.46410161514
Raíz cuadrada Sqrt($a) -7.3 NAN
Raíz enésima pow($a,(1/$b) 12 3 2.28942848511
Valor absoluto Abs($b) -7.3 7.3

Al realizar una operación cuyo resultado no es un número real PHP devuelve la cadena NaN tal como puedes
ver en el ejemplo de laraíz cuadrada de un número negativo.

Redondeo de resultados

PHP dispone de tres opciones de redondeo:

floor($z)

Redondeo por defecto

ceil($z)

Redondeo por exceso

round($z)

Redondeo tradicional

Redondeos
tipo Sintaxis A Resultado

Parte entera (int)$a 12 12


Parte entera (int)$a -7.3 -7
Parte entera (int)$a -13.8546 -13
Parte entera (int)$a -24.5 -24
Parte entera (int)$a 13.8546 13
Parte entera (int)$a 24.5 24
Redondeo por defecto floor($a) 12 12
Redondeo por defecto floor($a) -7.3 -8
Redondeo por defecto floor($a) -13.8546 -14
Redondeo por defecto floor($a) -24.5 -25
Redondeo por defecto floor($a) 13.8546 13
Redondeo por defecto floor($a) 24.5 24
Redondeo por exceso ceil($a) 12 12

Pág. 50
Redondeo por exceso ceil($a) -7.3 -7
Redondeo por exceso ceil($a) -13.8546 -13
Redondeo por exceso ceil($a) -24.5 -24
Redondeo por exceso ceil($a) 13.8546 14
Redondeo por exceso ceil($a) 24.5 25
Redondeo round($a) 12 12
Redondeo round($a) -7.3 -7
Redondeo round($a) -13.8546 -14
Redondeo round($a) -24.5 -25
Redondeo round($a) 13.8546 14
Redondeo round($a) 24.5 25

Orden de operación

Cuando una misma instrucción contiene una secuencia con varias operaciones el orden de ejecución de las
mismas sigue los mismos criterios que las matemáticas. No se realiza una ejecución secuencial sino que se respeta
el orden de prioridad matemático. Es decir, las potencias y raíces tienen prioridad frente a los productos y los cocientes,
y estos, son prioritarios respecto a la suma y las diferencias.

Igual que en matemáticas se pueden utilizar los paréntesis para modificar el orden de ejecución de las operaciones,
e igual que allíPHP también permite encerrar paréntesis dentro de paréntesis.

¡Cuidado!

Cuando realices operaciones combinadas, no olvides establecer –mediante paréntesis– las prioridades
que sean necesarias. ¡No temas abusar de ellos! Te evitarán muchos problemas.

Punto flotante y precisión arbitraria

Las funciones aritméticas que estamos estudiando utilizan la sintaxis de punto flotante cuya precisión es
limitada y, aunque depende del sistema, PHP típicamente utiliza el formato de doble precisión IEEE 754, el cual puede
dar un error relativo máximo por aproximación del orden de 1.11*10–16.

Las operaciones aritméticas más elementales nunca van a dar grandes errores aunque la dimensión de estos
podrá irse incrementando a medida que se concatenar varios de esos errores simples en operaciones compuestas.

Hay que tener en cuenta la existencia de fracciones que se pueden representar de forma exacta como números
de punto flotante en base 10 (por ejemplo 1/10 ó 7/10) pero que carecen de esa exactitud al ser expresados en base 2
que es la usada internamente por PHP.

Así pues, hemos de tener cuidado al considerar números de coma flotante hasta su último dígito por los
imprevisibles efectos –sobretodo a la hora de la comparación– de esos errores en el resultado.

Para operaciones matemáticas que necesiten una mejor precisión PHP (innecesaria en el ámbito cotidiano y
limitada a casos muy puntuales del ámbito científico) ofrece la calculadora binaria que soporta números de cualquier
tamaño y precisión representados como cadenas. Las funciones que utilizan esa forma de cálculo son las siguientes:

bcadd($a,$b,c)

Devuelve la suma de los valores numéricos contenidos en las cadenas $a y $b con una precisión (número de
cifras decimales) especificada por el número entero especificado en el parámetro c.

Pág. 51
bcsub($a,$b,c)

Devuelve la diferencia entre los valores numéricos contenidos en las cadenas $a y $b con una precisión (número
de cifras decimales) especificada por el número entero especificado en el parámetro c.

bcmul($a,$b,c)

Devuelve el producto de los valores numéricos contenidos en las cadenas $a y $b con una precisión (número de
cifras decimales) especificada por el número entero especificado en el parámetro c.

bcdiv($a,$b,c)

Devuelve el resultado de dividir los valores numéricos contenidos en las cadenas $a y $b con la precisión
especificada por el número entero contenido en el parámetro c.

bcmod($a,$b)

devuelve el resto de la división entera de los valores contenidos en las cadenas $a y $b.

bcpow($a,$b,c)

Devuelve el resultado de elevar el valor numérico contenido en la cadena $a a la potencia expresada por la
cadena $b dando el resultado con la cantidad de decimales señalada por el parámetro c.

bcsqrt($a,c)

Devuelve la raíz cuadrada del valor numérico contenido en la cadena $a con la cantidad de decimales señalada
por el parámetro c.

bccomp($a,$b,c)

Compara los valores contenidos en las cadenas $a y $b teniendo en cuenta únicamente el número 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 Compara 3 con 3 que obviamente son iguales


bccomp($a,$b,1)=0 Compara 34 con 34. Son iguales y por tanto devuelve cero
bccomp($a,$b,2)=0 Compara 345 con 345. Son iguales y por tanto devuelve cero
bccomp($a,$b,3)=1 Compara 3456 con 3450. No son iguales y por tanto devuelve uno

En el cuadro puedes ver, señalados en rojo, los resultados de efectuar la misma operación utilizando el operador
de coma flotante y estas funciones de precisión arbitraria. Si comparas las diferencias en los resultados obtenidos con
cada una de ellas podrás darte idea del error provocado por los inevitables redondeos de la operación con coma flotante.

Comparación de punto flotante y precisión arbitraria

Comparación de funciones matemáticas

Pág. 52
Operación Variable Valor

$A "12345678910123456789012345678901234567890"
$B "45678910123456789012345678901234567890123"
bcadd($A,$B,0) 58024589033580245801358024580135802458013
$a=(double)$A 1.23456789101E+40
$b=(double)$B 4.56789101235E+40
S 5.80245890336E+40 ó
$a+$b
U 58024589033580236333428572634998418440192
M $C "0.0002345678902"
A
$D "0.00000000000000000000000000000000000000001523786"
bcadd($C,$D,50) 0.00023456789020000000000000000000000000001523786000
$c=(double)$C 0.0002345678902
$d=(double)$D 1.523786E-41
0.0002345678902 ó
$c+$d
0,00023456789020000001029161995624860992393223568797
$A "12345678910123456789012345678901234567890"
$B "45678910123456789012345678901234567890123"
bcsub($A,$B,0) -33333231213333332223333333222333333322233
$a=(double)$A 1.23456789101E+40
$b=(double)$B 4.56789101235E+40
R -3.33332312133E+40 ó
E $a-$b
-33333231213333327795815413198205132734464
S
T $C "0.0002345678902"
A $D "0.00000000000000000000000000000000000000001523786"
bcsub($C,$D,50) 0.00023456789019999999999999999999999999998476214000
$c=(double)$C 0.0002345678902
$d=(double)$D 1.523786E-41
0.0002345678902 ó
$c-$d
0,00023456789020000001029161995624860992393223568797
$A "12345678910123456789012345678901234567890"
$B "45678910123456789012345678901234567890123"
56393715734858534797546128354926080723008626986848
bcmul($A,$B,0)
1383972550423718379870903950470
$a=(double)$A 1.23456789101E+40
$b=(double)$B 4.56789101235E+40
P
R 5.63937157349E+80 ó
O $a*$b 56393715734858529559076134525051001632068799181691
D 5078270593363632973621514731520
U $C "0.0002345678902"
C
T $D "0.00000000000000000000000000000000000000001523786"
O 0.000000000000000000000000000000000000000000003574
bcmul($C,$D,62)
312671362972
$c=(double)$C 0.0002345678902
$d=(double)$D 1.523786E-41
3.57431267136E-45 ´0
$c*$d 0,000000000000000000000000000000000000000000003574
31267136297184
$A "12345678910123456789012345678901234567890"

Pág. 53
$B "45678910123456789012345678901234567890123"
bcdiv($A,$B,30) 0.270270872854818178953756836882
$a=(double)$A 1.23456789101E+40
$b=(double)$B 4.56789101235E+40
D 0.270270872855 ó
$a/$b
I 0,270270872854818211550309570157
V
I $C "0.0002345678902"
S $D "0.00000000000000000000000000000000000000001523786"
I
Ó 15393755435474535138136194977509965310.08947450626
bcdiv($C,$D,30)
N 2690430283517501801
$c=(double)$C 0.0002345678902
$d=(double)$D 1.523786E-41
1.53937554355E+37 ó
$c/$d 15393755435474536238109275036946792448,00000000000
0000000000000000000
$A "12345678910123456789012345678901234567890"
R $B "57"
E
S bcmod($A,$B) 19
T $a=(double)$A 1.23456789101E+40
O
S $b=(double)$B 57
$a % $b 0
$A "12345678910123456789012345678901234567890"
$B "13"
15477282435120092620517640487873307882539433894477
02478876805675247359287360605519476488004915460644
30130253272627846453956411651820029120439549209342
P 64779279536097719586538292066102759581864670705845
O 47341619065960659102701030110334399943453939049941
T bcpow($A,$B) 81961179086427277645221130645386339095405377300948
E 55610257804029129290263282188925049521874093123594
N 94558994966581650612470024575134583192369561297975
C 69626211024080786875604177270092747586939296603680
I 65512433192215011092075340601280601173670507434702
A 7729224690000000000000
$a=(double)$A 1.23456789101E+40
$b=(double)$B 13
INF ó
pow($a, $b)
inf
$A "12345678910123456789012345678901234567890"
C
U $B "13"
R A bcsqrt($A,15) 111111110651111110153.9111071478030905799220364
A D
I R $a=(double)$A 1.23456789101E+40
Z A $b=(double)$B 13
D
A 1.11111110651E+20 ó
Sqrt($a)
111111110651111112704,0000000000000000000000000

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 pequeños) los errores relativos son
de escasa significación. En la inmensa mayoría de las situaciones (por no decir todas las cotidianas) resulta suficiente
utilizar los operadores de coma flotante.

Pág. 54
Logaritmos y trigonometría

Logarítmos y trigonometría

La sintaxis para el uso de las funciones logarítmicas y trigonométricas es esta:

log($a)

Devuelve el valor del logaritmo neperiano de valor numérico contenido en la variable $a

Log10($a)

Devuelve el valor del logaritmo decimal de valor numérico contenido en la variable $a

Exp($a)

Devuelve el valor del número e elevado a la variable $a (e$a)

Operaciones con logaritmos


Operación Sintaxis A Resultado

Logaritmo neperiano log($a) 12 2.48490664979


Logaritmo neperiano log($a) -7.3 NAN
Logaritmo decimal Log10($a) 12 1.07918124605
Logaritmo decimal Log10($a) -7.3 NAN
a
exponencial e Exp($a) 12 162754.791419
a
exponencial e Exp($a) 1 2.71828182846
a
exponencial e Exp($a) -7.3 0.000675538775194
a
exponencial 10 pow(10,$a) 12 1000000000000
a
exponencial 10 pow(10,$a) -7.3 5.01187233627E-8

Al realizar una operación cuyo resultado no es un número real PHP devuelve la cadena NAN tal como puedes
ver en los ejemplos delogaritmos de números negativos.

Las funciones trigonométricas tanto las directas como las inversas consideran los valores de los
angulos expresados en radianes.

pi()

devuelve el valor del número irracional π

Sin($a)

devuelve el valor del seno del angulo $a expresado en radianes

Cos($a)

Pág. 55
devuelve el valor del coseno del angulo $a expresado en radianes

Tan($a)

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

deg2rad($a)

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

Funciones trigonométricas
Operación Sintaxis A Resultado

Valor de PI Pi() 3.14159265359


Seno de A (radianes) Sin($a) 12 -0.536572918
Seno de PI (radianes) Sin(pi()) pi() 1.22464679915E-16
Coseno de A (radianes) Cos($a) 12 0.843853958732
Coseno de PI (radianes) Cos(pi()) pi() -1
Tangente de A (radianes) Tan($a) 12 0.843853958732
Tangente de PI (radianes) Tan(pi()) pi() -1.22464679915E-16
Tangente de PI/2 (radianes) Tan(pi()) pi()/2 1.63312393532E+16
Pasa grados a radianes deg2rad($a) 45 0.785398163397
Pasa grados a radianes deg2rad($a) 30.8 0.537561409614

Asin($a)

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

Acos($a)

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

Atan($a)

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

rad2deg($a)

convierte en grados sexagesimales la medida del angulo $a expresado en radianes

Funciones trigonométricas inversas


Operación Sintaxis A Resultado

Arco seno de A (en radianes) Asin($a) 0.8 0.927295218002


Arco seno de A (en radianes) Asin($a) 12 NAN
Arco coseno de A (en radianes) Acos($a) 0.8 0.643501108793
Arco coseno de A (en radianes) Acos($a) 12 NAN

Pág. 56
Arco tangente de A (en radianes) Atan($a) 0.8 0.674740942224
Arco tangente de A (en radianes) Atan($a) 12 1.48765509491
Pasa radianes a grados rad2deg($a) pi()/4 45

Pág. 57
Cambios de base y formatos

Formatos de las variables numéricas

En PHP, para asignar valores numéricos a una variable pueden utilizarse uno de los siguientes sistemas de
numeración:

Los números enteros pueden escribirse en una cualquiera de estas bases:

• Base decimal

$a=número

No se pueden insertar ceros a la izquierda cuando se escriben números en base decimal.

• Base octal

$a=0número octal

Basta poner un CERO delante del número para que sea interpretado como escrito en base OCTAL. Obviamente,
sólo admite los dígitos de 0 a 7.

• Base hexadecimal

$a=0xnúmero hexadecimal

Si se escribe CERO EQUIS (0x) delante del número, PHP lo interpretará como expresado en hexadecimal. En
este caso, admitirá como dígitos de 0 a 9 y de A a F.

Un número de coma flotante puede escribirse de cualquiera de estas formas:

• Notación decimal.

$a=número

Se puede utilizar un cero a la izquierda del punto decimal.

• Notación científica

$a=número 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 105.
Cuando el exponente es negativo $a=1.2e-5 asigna a $a el valor: 1.2 x 10-5

Asignación de valores en distintas bases


Base Sintaxis Valor decimal Aplicable a

Base Decimal $a=17 17 Números enteros


Base Octal $a=017 15 Números enteros
Base Hexadecimal $a=0x17 23 Números enteros
Base Hexadecimal $a=0x1A3B 6715 Números enteros
Notación decimal $a=123000; 123000 Coma flotante
Base Decimal $a=0.174 0.174 Coma flotante

Pág. 58
Notación científica $a=1.23e5; 123000 Coma flotante
Notación científica $a=23.4e-2; 0.234 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.

Asignación de valores en distintas bases


Valor de la variable Base Nueva base Sintaxis Expresión
$a=1234 10 8 decoct($a) 2322
$a=1234 10 16 dechex($a) 4d2
$a=1234 10 2 decbin($a) 10011010010
$a=1234 8 10 octdec($a) 668
$a=1234 16 10 hexdec($a) 4660
$a=1010011 2 10 bindec($a) 83
$a=1234 7 14 base_convert($a,7,14) 254
$a=1234 5 18 base_convert($a,5,18) ae
$a=1234 18 5 base_convert($a,18,5) 202123

Presentaciones numéricas

La presentación de los valores numéricos permite una gran variedad de formatos.

El número de cifras decimales, los separadores de decimales y los separadores de mil pueden configurarse a voluntad
utilizando alguna de estas funciones.

number_format (número)

Presenta la parte entera del número (sin decimales) y utiliza como separador de miles una coma (,).

number_format (número , número de cifras decimales)

Presenta el número de cifras decimales que se indiquen y utiliza como separador decimal un punto (.) y el
separador de miles es una coma (,).

number_format (número , núm decimales , "sep. decimal" , "sep. miles")

Permite establecer el número de cifras decimales de la presentación así como el carácter que se establezca como
separador de decimales y como separadores de miles.

¡Cuidado!. No te olvides de escribir los caracteres de separación entre comillas.

Formatos de presentación de número


Valor Nº de Sep. Sep.
Sintaxis Resultado
inicial decimales dec. miles
$a=1234567.234 0 , number_format($a) 1,234,567
$a=1234567.234 2 . , number_format($a,2) 1,234,567.23
$a=1234567.234 1 , . number_format($a ,1 , "," ,".") 1.234.567,2
$a=1234567.234 1 ' esp number_format($a ,1 , " ' " ," ") 1 234 567'2

Pág. 59
Números aleatorios

El valor Unix Epoch

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

time()

La función time() devuelve el número 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 443 835 933 segundos

microtime()

Usando la función microtime() se obtiene una cadena que, además del número 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.02193600 1443835933 . Como verás, aparece
la fracción decimal del tiempo Unix Epoch delante de su valor entero.

(double)microtime()

Dado que microtime() devuelve una cadena, es posible convertirla en número de coma
flotante anteponiendo (double) que, como recordarás, es la función que permite forzar una cadena a número coma
flotante. Una vez cambiado el tipo de variable el valor devuelto pormicrotime se convierte en: 0.021943 que como puedes
observar es un número con seis decimales (si las últimas cifras son ceros no se visualizarán).

Si se multiplica el valor anterior por 1.000.000 obtenemos un número entero de seis cifras que cambia de valor
cada millonésima de segundo. Observa el resultado de esta operación: 21952 ¡Fíjate que ha cambiado! La diferencia
no es otra cosa que el tiempo transcurrido entre los instantes en que se ejecutaron ambas instrucciones.

Números aleatorios

PHP dispone de dos funciones capaces de generar números aleatorios. Se trata de la función rand() y de la función
mejoradamt_rand().

Generación de un número aleatorio


Generador rand() Generador mt_rand()
Sintaxis Nº aleatorio Sintaxis Nº aleatorio
echo rand() 1767734481 echo mt_rand() 383098643

El número aleatorio generado está comprendido entre CERO y un valor máximo que puede determinarse para
cada una de las dos opciones mediante las funciones getrandmax() y mt_getrandmax() Estos son sus valores.

Valores máximos de los generadores de números aleatorios


Generador rand() Generador mt_rand()
Sintaxis Valor máximo Sintaxis Valor máximo
echo getrandmax() 2147483647 echo mt_getrandmax() 2147483647

Según las librerías que esté usando PHP, puede ocurrir que los valores máximos con ambos generadores sean
iguales.

Pág. 60
Una semilla que mejora la aleatoriedad

Se pueden ejecutar las funciones srand() o mt_srand() incluyendo en ellas una expresión como la especificada
en rojo

srand((double)microtime()*1000000)
mt_rand((double)microtime()*1000000)

antes de invocar a las funciones rand() o mt_rand(). De esta forma estaremos introduciendo una semilla cuyo
valor, tal como comentamos en el epígrafe anterior, se modifica cada millonésima de segungo y que mejora
sustancialmente la aleatoriedad de los números obtenidos.

Aquí tenemos un ejemplo:

Generación de un número aleatorio con semilla


Generador rand()
Sintaxis Nº aleatorio
srand((double)microtime()*1000000);
1594318098
echo rand()
Generador mt_rand()
Sintaxis Nº aleatorio
mt_srand((double)microtime()*1000000);
82223502
echo mt_rand()

Manteniendo la sintaxis anterior –no te olvides de incluir las semillitas– se pueden generar números aleatorios
comprendidos dentro del intervalo que preestablezcamos. Bastaría con añadir los valores de los extremos de
ese intervalo como parámetros de la función. La sintaxis sería esta:

rand(extremo inferior , extremo superior)

y para la función mejorada

mt_rand(extremo inferior , extremo superior)

Generación de un número aleatorio delimitando intervalos


Generador rand()
Sintaxis Nº aleatorio
srand((double)microtime()*1000000);
274
echo rand(1,300)
Generador mt_rand()
Sintaxis Nº aleatorio
mt_srand((double)microtime()*1000000);
61
echo mt_rand(1,300)

Pág. 61
Variables tipo cadena

Las variables de cadena

A las variables tipo cadena se les puede asignar los valores escribiendo el contenido entre comillas $var="Texto
del contenido"; o por medio de la conocida como sintaxis de documento incrustado que es la siguiente:

$var= <<< EOD


... contenido de la cadena...
... puede ir ....
.. en varias líneas...
EOD;

donde EOD es una palabra cualquiera que debe repetirse exactamente igual al final de la instrucción.

La sintaxis de documento inscrutado requiere tener presentes algunas consideraciones:

 El nombre de la variable, el signo igual que la precede, los tres símbolos < y el EOD deben escribirse en la misma
línea, que esta vez no irá acabada en punto y coma (observa que no acaba allí la instrucción).
 Puede incluirse el texto (valor de la variable) en tantas líneas como se desee, pero hay que tener en cuenta que a la
hora de visualizar el documento no se mantiene esa estructura ya que HTML sólo entiende la etiqueta <BR> como
indicador de salto de línea.
 El cierre de la instrucción debe hacerse –siempre– escribiendo el EOD al comienzo una nueva línea –independiente–
que ahora sí tiene que llevar el punto y coma que indica a PHP el final de una instrucción.

Aquí tienes un ejemplo en el que se utilizan las dos formas de asignación de valores a una cadena.

<html>
<head>
<title>Ejemplo 34 - PHP</title>
</head>
<body>
<?php
$cadena1="Esto es una cadena de texto";

$cadena2= <<<Pepe
Esta es otra cadena escrita
con la sintaxis de documento incrustado.
Se escribe en varias líneas y tiene la sintaxis
siguiente. Después 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 línea y escribir el texto con las líneas que
se desee, pero cuidado... a la hora de visualizar la cadena
con la instrucción echo todo este texto se verá seguido
ya que para que se visualizaran saltos de línea en una página
web habría que poner las famosas etiquetas <BR>.
Se indica el final de la cadena escribiendo de nuevo
el nombre asignado en la primera línea -Pepe- pero teniendo
la precaución de escribirlo en una linea nueva al final de
todo el texto... Así como lo ves en el código 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;

Pág. 62
echo $cadena1,"<br>";
echo $cadena2,"<br>";
echo $cadena3,"<br>";
?>
</body>
</html>

ejemplo34.php

Pág. 63
Operaciones con cadenas

La concatenación de cadenas

Para concatenar (unir en una sola cadena) varias porciones de texto hemos venido utilizando –en las
instrucciones print y echo– un punto (.).

Este punto (.) es un elemento muy importante que, además de la forma que hemos visto en las páginas anteriores,
tiene los siguientes usos:

• Unir dos cadenas y recogerlas en una variable

$a="cad1" . "cad2"; o $a= $b . $c

podemos obtener una nueva variable formada por la unión dos trozos. Pero seguramente te preguntarás ¿qué
ocurre si juntamos una variable cadena y una numérica? o ¿qué ocurre si juntamos dos variables numéricas?

En cualquiera de los supuestos –puedes verlo en el ejemplo– las variables serán 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.

• Añadir contenidos a una variable tipo string

$a .="cad1" o $a .=$b

Si utilizamos una sintaxis como esta (presta mucha atención al punto que va delante del signo igual)
se añadiría al valor actual de la variable $a el contenido indicado después del signo igual. Fíjate en la importancia del
punto. Si está presente se añaden nuevos contenidos a la variable. En el caso de que no estuviera se asignaría a la
variable únicamente lo incluido después del signo igual.

Aquí tienes un ejemplo de concatenación 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 numéricas


$cadena3=127;
$cadena4=257.89;

# unámoslas 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


# añadiendole contenidos

$cadena3 .=" Este es el texto que se añadirá a la variable cadena3";


# imprimamos los resultados
echo $cadena3,"<br>";
# añadamos ahora un nuevo trozo, esta vez

Pág. 64
# a partir de una cadena escrita con la
# sintaxis de documento incrustado
$cadena3 .= <<<Pepito
Ahora le añado a la cadena
este trocillo asignado con el "formato"
de documento incrustado
Pepito;
# visualicemos el resultado
echo $cadena3,"<br>";
?>

ejemplo35.php

Pág. 65
Array escalar y asociativo

¿Qué es un array?

Un array es algo tan simple una tabla de valores. Cada uno de los elementos de esa tabla se identifica por medio
de un nombre (común para todos) y un índice (que sería el elemento diferenciador de cada uno de ellos).

Mediante el uso de arrays podemos utilizar el mismo nombre para varias variables diferenciándolas por medio
de sus índices. La sintaxis que permite definir elementos en un array es esta:

$nombre[indice]

dónde $nombre utiliza exactamente la misma sintaxis empleada para definir variables, con la única particularidad
de que ahora deben añadírsele los corchetes y los índices. El índice puede ser un número (habría que escribirlo dentro
del corchete sin comillas), una cadena (que habría que poner en el corchete encerrada entre comillas sencillas –'–), o una
variable que tampoco necesitaría ir entre comillas.

Cuando los índices de un array son números se dice que es escalar mientras que si fueran cadenas se le llamaría
array asociativo.

Tablas unidimensionales
Array escalar Array asociativo
Variable Indice Valor Variable Indice Valor
$a[0] 0 Domingo $a['Primero'] Primero Domingo
$a[1] 1 Lunes $a['Segundo'] Segundo Lunes
$a[2] 2 Martes $a['Tercero'] Tercero Martes
$a[3] 3 Miércoles $a['Cuarto'] Cuarto Miércoles
$a[4] 4 Jueves $a['Quinto'] Quinto Jueves
$a[5] 5 Viernes $a['Sexto'] Sexto Viernes
$a[6] 6 Sábado $a['Septimo'] Septimo Sábado

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 automática 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 número correspondiente al valor del
índice. Si ya existiera un elemento con ese índice, se cambiaría el valor de su contenido, en caso contrario creará un
nuevo elemento del array y se le asignaría como valor lo especificado detrás del signo igual que –de la misma forma que
ocurría con las variables– debería ir entre comillas si fuera una cadena o sin ellas si se tratara de un número.

En el tercero de los supuestos, la palabra array que precede al paréntesis indica que cada uno de los valores –
numéricos o cadenas– separados por comas e incluidos dentro del paréntesis son los valores correspondientes a los
elementos de índices 0, 1, 2... de un array escalar.

Pág. 66
Arrays asociativos

Los elementos de un array asociativo (aquel cuyos índices no son números) 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 también 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 sería este

$a[$indice]=valor

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

Ejemplo de arrays unidimensionales

<?php
# Crearemos un array escalar (basta con definir un elemento)
$a[2]="Este elemento es el segundo del array";
# creemos un nuevo elemento de ese array
# esta vez de forma automática
# si ponemos corchetes vacíos va añadiendo índices automaticamente
$a[]="¿Será este tercero?";
# comprobemos que le ha puesto índice 3
echo "El elemento ".$a[3]." tiene indice 3 (siguiente a 2) <br>";
# ahora insertemos un nuevo elemento con indice 32
$a[32]="Mi indice es 32";
# insertemos otro elemento de forma automática
$a[]= "¿Irá a parar al indice 33 este elemento?";
# la inserción se hará con indice 33, comprobémoslo
print "Vemos que contiene el elemento de indice 33 ...".$a[33]."<br>";
# ¿qué ocurrirá si pido que imprima el elemento 21 que nadie ha definido
# seguramente estará vacio, ¡¡comprobémoslo!!
# antepondremos el @ para evitar el mensaje de advertencia de PHP
@print ("Aqui--> ". $a[21]. "<--- si es que hay algo<br>");
# ahora crearemos un nuevo array llamado $b
# insertémosle de forma automatica su PRIMER elemento
$b[]="Estoy empezando con el array b y mi indice será cero";
# comprobemos que efectivamente ha empezado con indice CERO
print ($b[0]."<br>");
# veamos ahora eso de los arrays asociativos
# creemos uno llamado $c con varios elementos
$c["objeto"]="coche";
$c["color"]="rojo";
$c["tamaño"]="ideal";
$c["marca"]= "Ferrari";
$c["precio"]="prohibitivo para un humilde docente";
#encadenemos variables para hacer una salida
# pondremos cadenas " " para que no aparezcan los textos
# pegados unos a otros..
$salida="<H2> El ". $c["objeto"] ." ".$c["marca"]." ".$c["color"];
$salida .=" tiene el tamaño ideal ".$c["tamaño"];
$salida .=" y su precio es ".$c["precio"];
$salida .="</H2>";
print $salida;
# sigamos experimentando ahora
Pág. 67
# ¿qué ocurriría si nos olvidamos de poner nombre al indice
# e insertamos un corchete vacio ¿lo crearía?¿que indice pondria?
# probemos ....
$c[]="¿creará un array escalar nuevo y le pondrá indice cero?";
# tratemos ahora de visualizar esa variable
# probemos a escribir $c[0] porque PHP
# habrá entendido que queremos un array escalar
# y como no existe ninguno con ese nombre empezará por cero
# comprobémoslo
echo $c[0];
?>

ejemplo36.php

Pág. 68
Arrays bidimensionales

Arrays bidimensionales

Los arrays bidimensionales pueden entenderse como algo bastante similar a una tabla de
doble entrada. Cada uno de los elementos se identifica –sigue siendo válido el nombre único que se
usaba en los unidimensionales– por un nombre ($nombre) seguido de dos ([ ]) que contienen
los índices (en este caso son dos índices) del array.

Los índices pueden ser de tipo escalar -equivalen al número de fila y columna que
la celda ocupa en la tabla– asociativos lo que equivaldría en alguna medida a usar como índices
los nombres de la fila y de la columna y también mixtos (uno de los índices es escalar y el otro
asociativo).

¡Cuidado!

No dejes de tener en cuenta lo que hemos advertido al hablar de arrays unidimensionales.

En este supuesto, también, se empiezan a numerar los arrays escalares a partir de CERO.

Arrays bidimensionales escalares

Los elementos de un array bidimensional escalar pueden escribirse usando una de estas
sintaxis:

$a[ ][ ]=valor o $a[xx][ ]=valor o $a[ ][xx]=valor o también $a[xx][yy]=valor

En el primero de los casos PHP asigna automáticamente 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, aún 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 más alto de todos aquellos cuyo primer
índice coincide con el especificado.

La tercera opción es bastante similar a la anterior. Ahora se modificaría automáticamente el


primer índice y se escribiría el contenido (xx) como valor del segundo.

En la cuarta de las opciones se asignan libremente cada uno de los índices (xx e yy)
poniéndoles valores numéricos.

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

Pág. 69
$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 automático en ambos indices
# de esta forma el primero tomará valor uno (siguiente al anterior)
# de forma automática
$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 verás el proceso no tiene complicaciones, pero ... pesadillo si es


# ¿verdad que si tuviéramos una base de datos sería más fácil?
# estamos en ello, todo se andará...

# tendríamos 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

# Sería 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 estéticos, hemos construido esta tabla:

Todos los resultados de la liguilla


Indice 0 1 2 3 4

Pág. 70
0 3-2 5-3 7-1 0-2
1 0-11 2-1 1-0 1-2
2 0-0 1-3 1-4 2-0
3 1-0 6-3 14-3 1-0
4 1-1 2-3 0-1 1-1

Arrays bidimensionales asociativos

Los elementos de un array asociativo bidimiensional se pueden escribir usando la siguiente


sintaxis:

$a["indice1"]["indice2"]=valor

En este caso, los índices serán cadenas y se escribirán entre comillas.

Como ejemplo de array bidimensional emplearemos una tabla de resultados de una liga de
fútbol 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 Piloñesa
Juvencia 3-2 5-3 7-1 0-2
Mosconia 0-11 2-1 1-0 1-2
Canicas 0-0 1-3 1-4 2-0
Condal 1-0 6-3 14-3 1-0

Piloñesa 1-1 2-3 0-1 1-1

Pág. 71
Arrays multidimensionales

Arrays multidimensionales

PHP permite el uso de arrays con dimensión superior a dos. Para modificar la dimensión del array basta con ir
añadiendo nuevos índices.

$a[x][y][z]=valor;

asignaría un valor al elemento de índices x, y y z de un array tridimensional

$a[x][y][z][w]=valor;

haría lo mismo, ahora con un array de dimensión cuatro.

Pueden tener cualquier tipo de índices: escalares, asociativos y, también, mixtos.

La función array();

Para asignar valores a una matriz puede usarse la función 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 función array() permite escribir arrays de cualquier dimensión utilizando la técnica 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,
)
);

Pág. 72
Como puedes observar, se trata de sustituir los valores asignados a los elementos de una primera
función array() por otra nueva función array que contiene los segundos índices asi como los valores asignados a los
mismos.

El anidado sucesivo permitiría generar arrays de cualquier dimensión.

Aunque en el ejemplo anterior nos hemos referido a un array escalar, idéntico procedimiento sería válido
para arrays asociativos con sólo cambiar los números por cadenas escritas entre comillas.

Este podría 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 podría definirse también 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 dimensión se hace mayor la sintaxis requiere muchísima más atención 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 también con los paréntesis.
 – Cierra cada uno de los paréntesis que abras y no olvides que los paréntesis se anidan, ya sabes... el primero que se
abre siempre con el último que se cierra, el segundo con el penúltimo, etcétera.
 – No dejes de prestar atención 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",
Pág. 73
"Penalty" => "2"
),
"Condal" => array (
"Resultado" => "7-1",
"Amarillas" => "5",
"Rojas" => "2",
"Penalty" => "1"
),
"Piloñesa" => 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"
),
"Piloñesa" => 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" => " ",
Pág. 74
"Rojas" => " ",
"Penalty" => " "
),
"Condal" => array (
"Resultado" => "1-4",
"Amarillas" => "2",
"Rojas" => "1",
"Penalty" => "1"
),
"Piloñesa" => array (
"Resultado" => "2-0",
"Amarillas" => "1",
"Rojas" => "0",
"Penalty" => "0"
),
),
"Condal" => array(
"Juvencia" => array (
"Resultado" => "1-0 ",
"Amarillas" => "4",
"Rojas" => "1",
"Penalty" => "2"
),
"Mosconia" => array (
"Resultado" => "6-3",
"Amarillas" => "1",
"Rojas" => "2",
"Penalty" => "3"
),
"Canicas" => array (
"Resultado" => "14-3",
"Amarillas" => "1",
"Rojas" => "0",
"Penalty" => "0"
),
"Condal" => array (
"Resultado" => " ",
"Amarillas" => " ",
"Rojas" => " ",
"Penalty" => " "
),
"Piloñesa" => array (
"Resultado" => "1-0",
"Amarillas" => "3",
"Rojas" => "1",
"Penalty" => "0"
),
),
"Piloñesa" => 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",
Pág. 75
"Amarillas" => "0",
"Rojas" => "0",
"Penalty" => "0"
),
"Condal" => array (
"Resultado" => "1-1",
"Amarillas" => "1",
"Rojas" => "2",
"Penalty" => "0"
),
"Piloñesa" => array (
"Resultado" => " ",
"Amarillas" => " ",
"Rojas" => " ",
"Penalty" => " "
),
)
);
?>

ejemplo38.php

Pág. 76
Presentación de números

Funciones de salida

Ya conocemos algunas de las funciones que PHP utiliza para mostrar información –salidas– en la ventana del
navegador del cliente.

Recordémoslas:

echo

La función echo, aunque admite también la forma echo(), no requiere de forma obligatoria el uso de los paréntesis.
Detrás de lainstrucción echo pueden insertarse: variables, cadenas (éstas entre comillas) y números (éstos sin comillas)
separadas por comas.

Este es un ejemplo de código:

$a=24; $b="Pepe"; $c="<br>"; echo $a,$b,25, "Luis",$c; que produciría esta salida: 24Pepe25Luis

print()

La función print() sólo puede contener dentro del paréntesis una sola variable, o el conjunto de varias de ellas
enlazadas por un punto. Aquí tienes algunos ejemplos:

print(25.3) produciría esta salida 25.3


print("Gonzalo") escribiría Gonzalo
$z=3.1416; print($z); escribiría 3.1416

Recuerda también que es posible utilizar dentro del paréntesis el concatenador de cadenas.

$h=3; $f=" hermanos"; print("Heladeria ".$h.$f) que escribiría Heladeria 3 hermanos

Salidas con formato

Ni la función echo, ni tampoco print permiten establecer una presentación (formato) en sus salidas, excepto que
alguna de las variables que se use contenga el resultado de una función number_format.

La función printf() ofrece un gran número de posibilidades en este sentido. Tanto la sintaxis como los valores de
los diferentes parámetros –cuando se trate de presentar números– las tienes resumidas en la tabla.

En la página siguiente veremos el uso de printf() para el tratamiento de variables tipo cadena.

Sintaxis
printf(cadena de formato,variable1,variable2,..)
Cadena de formato
"%[relleno][alineación][ancho][precisión][tipo]"
Carácter Valor Sintaxis Resultado
0 0 printf("%020d",32) 00000000000000000032
* '* printf("%'*20d",32) ******************32
espacio1) ' printf("%' 20d",32) 32
- '- printf("%'-20d",32) ------------------32
Relleno
Observaciones
En este apartado prestaremos atención únicamente a los caracteres marcados en rojo, que son los
que corresponden a las diferentes formas de relleno. Los demás parámetros los iremos tratando uno
en los apartados siguientes.

Cuando se pretende rellenar con ceros –a la izquierda– basta escribir el 0 inmediatamente detrás del

Pág. 77
signo %

Si se trata de rellenar con un carácter distinto de cero debe escribirse inmediatamente después
de% una comilla simple ' seguida del carácter de relleno.

Si se pretende rellenar con espacios forzados se puede escribir la comilla simple 'einmediatamente
después teclear la combinación ALT+0160 (carácter ASCII 160) usando el teclado numérico. Aunque
obviamente no se visualiza el espacio si se conserva tal como puede verse en el ejemplo 1)

Obsérvese que como la tipografía es de ancho variable y que según el carácter que se use como
relleno se modifica el ancho de la presentación.

Quizá convenga recordar que 32 es en este caso la variable a la que pretendemos dar formato y que
ese valor podría ser sustituido por el nombre de una variable que contenga valores numéricos.

Carácter Valor Sintaxis Resultado


Ninguno Dcha printf("%020d",32) 00000000000000000032
- Izda printf("%0–20d",32) 32
Ninguno Dcha printf("%'*20d",32) ******************32
- Izda printf("%'*–20d",32) 32******************
Ninguno Dcha printf("%020s",32) 00000000000000000032
- Izda printf("%0–20s",32) 32000000000000000000
Ninguno Dcha printf("%'*20s",32) ******************32
- Izda printf("%'*–20s",32) 32******************
Alineación Observaciones
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.

Fíjate que en los cuatro primeros supuestos el identificador de tipo es d, lo cual hace que considere la
variable como numérica, 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 numérica con ceros por la derecha PHP los omite para no
alterar el valor numérico en la presentación

Con cualquier otro carácter de relleno (incluidos los caracteres numéricos con ' delante) sí efectúa el
relleno.

Carácter Valor Sintaxis Resultado


Entero 14 printf("%'*14d",32) ************32
Entero 17 printf("%'*-17d",32) 32***************
Decimal 14.5 printf("%'*14.5d",32) ************32
Decimal 17.8 printf("%'*-17.8d",32) 32***************
Decimal 14.5 printf("%'*14.5f",32) ******32.00000
Ancho Decimal 11.8 printf("%'*-11.8f",32) 32.00000000

Observaciones
El ancho (nº de caracteres totales) puede especificarse mediante un número entero para todo tipo de
variables

Si se expresa mediante un número decimal y la variable es tipo coma flotante la parte decimal indica
la precisión (nº de cifras decimales) y la parte entera el ancho como número de caracteres de la parte
entera o de la parte decimal, según se rellene a la derecha o a la izquierda.

Tipo Valor Sintaxis Resultado


Presentación
b printf("%'*14b",17) *********10001
en forma binaria
Caracter
correspondiente c printf("%'*14c",97) a
al código ASCII
Número
Tipo presentado d printf("%'*14d",17.83) ************17
como entero
Número
presentado f printf("%'*14f",17.45) *****17.450000
con decimales
Presentación
o printf("%'*14o",17) ************21
en forma octal
Presentación
x printf("%'*14x",170) ************aa
en hexadecimal

Pág. 78
Presentación
X printf("%'*14X",170) ************AA
en hexadecimal
Presentación
s printf("%'*14s",170) ***********170
como >cadena

Pág. 79
Cadenas alfanuméricas (I)

Funciones sobre cadenas

Algunas de las funciones que permiten manejar los formatos de las cadenas de caracteres son estas:

chr(n)

Devuelve el carácter cuyo código ASCII es n.

ord(cadena)

Devuelve el código ASCII del primero de los caracteres de la cadena.

strlen(cadena)

Devuelve la longitud (número de caracteres) de la cadena. Los espacios son considerados como un caracter más.

strtolower(cadena)

Cambia todos los caracteres de la cadena a minúsculas.

strtoupper(cadena)

Convierte en mayúsculas todos los caracteres de la cadena.

ucwords(cadena)

Convierte a mayúsculas la primera letra de cada una de las palabras de la cadena.

ucfirst(cadena)

Convierte a mayúsculas la primera letra de la cadena y pone en minúsculas todas las demás.

ltrim(cadena)

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

rtrim(cadena)

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

trim(cadena)

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

Pág. 80
chop(cadena)

Elimina los espacios al final de la cadena. Es idéntica a rtrim.

¡Cuidado!

Tanto trim, como ltrim y rtrim eliminan, además de los espacios, las secuencias: \n, \r, \t, \v y \0; llamadas
tambiéncaracteres protegidos.

substr(cadena,n)

Si el valor de n es positivo extrae todos los caracteres de la cadena a partir del que ocupa la posición enésima a
contar desde la izquierda.

Si el valor de n es negativo serán extraídos 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 posición enésima, 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
posición enésima contada de derecha a izquierda.

Si n es positivo y m es negativo extrae la cadena comprendida entre el enésimo carácter (contados de izquierda
a derecha) hasta elemésimo, contando en este caso de derecha a izquierda

Si n es negativo y m también es negativo extrae la porción de cadena comprendida entre el emésimo y


el enésimo caracteres contando, en ambos casos, de derecha a izquierda. Si el valor absoluto de n es menor que el
de m devuelve una cadena vacía.

strrev(cadena)

Devuelve la cadena invertida

str_repeat(cadena, n)

Devuelve la cadena repetida tantas veces como indica n.

str_pad(cadena, n, relleno, tipo)

Añade a la cadena los caracteres especificados en relleno (uno o varios, escritos entre comillas) hasta que alcance
la longitud que indica n (un número)

El parámetro 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

Pág. 81
substr_replace(cadena, sustituto, comienzo, longitud)

Sustituye por sustituto un número de caracteres igual a longitud contados a partir del que ocupa la
posición 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 sustitución. Si el valor de longitud es negativo no sustituirá al final
de la cadena un número de carácteres igual al valor absoluto de longitud.

Estos son algunos ejemplos de aplicación de las funciones de manejo de cadenas

Código ASCII y viceversa


Función Ejemplo Resultado
chr(código ASCII) chr(97) a
ord("cadena") ord("abadesa") 97
Longitudes y conversiones mayúsculas/minúsculas
Función Ejemplo Resultado
strlen("cadena") strlen("Mide la longitud de esta cadena") 31
strtolower("cadena") strtolower("CONVIERTE A MINÚSCULAS") convierte a minÚsculas
strtoupper("cadena") strtoupper("pasa a mayúsculas") PASA A MAYúSCULAS
ucwords("cadena") ucwords("todas empiezan por mayúscula") Todas Empiezan Por Mayúscula
ucfirst("cadena") ucfirst("mayúscula al principio") Mayúscula al principio
Eliminar espacios
Función Ejemplo Resultado
ltrim("cadena") ltrim("\n \nEliminar espacios") Eliminar espacios
rtrim("cadena") rtrim("Eliminar espacios\n \n") Eliminar espacios
trim("cadena") trim("\n \nEliminar espacios\n \n") Eliminar espacios
chop("cadena") chop("\n \nEliminar espacios\n \n") Eliminar espacios
Extraer porciones de una cadena
Función Ejemplo Resultado
substr("cadena",n) substr("Extrae caracteres",3) rae caracteres
substr("cadena",n) substr("Extrae caracteres",0) Extrae caracteres
substr("cadena",n) substr("Extrae caracteres",-5) teres
substr("cadena",n) substr("Extrae caracteres",-2) es
substr("cadena",n,m) substr("Extrae caracteres",2,6) trae c
substr("cadena",n,m) substr("Extrae caracteres",0,8) Extrae c
substr("cadena",n,m) substr("Extrae caracteres",2,-3) trae caracte
substr("cadena",n,m) substr("Extrae caracteres",-7,5) acter
substr("cadena",n,m) substr("Extrae caracteres",-7,-5) ac
substr("cadena",n,m) substr("Extrae caracteres",-5,-7)
Modificaciones de cadenas
Función Ejemplo Resultado
strrev("cadena") strrev("Invierte la cadena") anedac al etreivnI
str_repeat("cadena",n) str_repeat("Rep",5) RepRepRepRepRep
str_pad("cadena",n,"Relleno",Tipo) str_pad("Pepe",10,"*",STR_PAD_BOTH) ***Pepe***
str_pad("cadena",n,"Relleno",Tipo) str_pad("Pepe",10,"*",STR_PAD_LEFT) ******Pepe
str_pad("cadena",n,"Relleno",Tipo) str_pad("Pepe",10,"*",STR_PAD_RIGHT) Pepe******
str_pad("cadena",n,"Relleno",Tipo) str_pad("Pepe",10,"*") Pepe******
str_replace ("lo que dice",lo que dira,"Cadena") str_replace("e","a","Pepe") Papa
str_replace ("lo que dice",lo que dira,"Cadena") str_replace("pe","pa","Pepepe") Pepapa
str_replace ("lo que dice",lo que dira,"Cadena") str_replace("Pepe","Luis","Pepe") Luis
substr_replace ("Cadena",lo que dira,n,m) substr_replace("Esta es una cadena es de prueba","*",5,2) Esta * una cadena es de prueba
substr_replace ("Cadena",lo que dira,n,m) substr_replace("Esta es una cadena es de prueba","*",5,-2) Esta *ba
substr_replace ("Cadena",lo que dira,n,m) substr_replace("Esta es una cadena es de prueba","*",-5,2) Esta es una cadena es de p*eba
substr_replace ("Cadena",lo que dira,n,m) substr_replace("Esta es una cadena es de prueba","*",-5,-2) Esta es una cadena es de p*ba

Pág. 82
Formatos en cadenas

La funcion prinf tiene un comportamiento idéntico al comentado en la página anterior.

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

Cadena de formato

Dentro de la cadena de formatos deben repetirse tantos formatos como variables se pretenda manejar

"%[rell1][alin1][anc1][prec1][tipo1][sepa1]%[rell1][alin1][anc1][prec1][tipo1][sepa1]"

Hemos de mencionar aquí los separadores ya que no fueron mencionados en la página anterior

Se puede introducir una cadena de separación al final de una cadena de formato que puede
hacer, entre otras, función de separación entre dos cadenas.
Por ejemplo, printf("%'*15.2f Euros",1475.875) nos devolvería:

********1475.88 Euros

La función printf() permite presentar varios valores o variables con distintos formatos utilizando
la sintaxis que se indica más 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 función PHP con características muy similares a la anterior. Se trata de sprintf().

La sintaxis es idéntica 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 aplicación del formato.

Pág. 83
Cadenas alfanuméricas (II)

Funciones sobre cadenas

Como complemento a las descritas en la página anterior, añadimos aquí algunas otras funciones PHP que también
permiten manejarcadenas de caracteres.

AddSlashes(cadena)

Inserta el carácter \ delante los siguientes: "(comillas dobles), ' (comillas simples), \ (escape) y NUL (el bit nulo).

stripslashes(cadena)

Quita las marcas añadidas a una cadena con la función AddSlashes().

chunk_split(cadena, nº caracteres, separador )

Devuelve la cadena cadena después de haberle insertado, cada nº caracteres, la cadena indicada en el
parámetro separador. Si no se indica separador PHP pondrá un espacio. Si no se establece el parámetro nº
caracteres insertará el separador cada 76 caracteres. Esta función 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 señalan 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 señalados como (separador) hasta el máximo de porciones señaladas (numero). Los
caracteres separadores no son incluídos 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 idéntica a implode.

strtok(cadena, separador)

Esta función 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.

Pág. 84
Marcas, divisiones y uniones de cadenas
Variable cadena Sintaxis Resultado
$a="Esta ' y \ y también NUL" AddSlashes($a) $a="Esta \' y \\ y también NUL"
$a="Esta \' y \\ y también NUL" stripslashes($a) Esta ' y y también el nulo
Esta –es un–a cad–ena l–arga –que p–resun–tamen–te
$a="Esta es una cadena larga que presuntamente será troceada" chunk_split($a,5,"–")
se–rá tr–ocead–a–
Esta es un a cad ena l arga que p resun tamen te se rá
$a="Esta es una cadena larga que presuntamente será troceada" chunk_split($a,5)
tr ocead a
Esta es una cadena larga que presuntamente será
$a="Esta es una cadena larga que presuntamente será troceada" chunk_split($a,76,"-")
troceada-
$todo="v1=Esto+sera+una+variable&v2=esto+otra&p[]=incluso+un+array"
parse_str($todo);
Esto sera una variable
echo $v1;
Divide la cadena $todo en sus componentes esto otra
echo $v2;
incluso un array
echo $p[0];
$a="Esta cadena sera devuelta en trozos"
$trozo1=explode(" ",$a);
echo $trozo1[0]; Esta
echo $trozo1[1]; cadena
Recogerá en un array cada uno de los trozos delimitados por los echo $trozo1[2]; sera
separadores echo $trozo1[3]; devuelta
echo $trozo1[4]; en
echo $trozo1[5]; trozos
>
$trozo2=explode("a",$a);
Est
echo $trozo2[0];
c
echo $trozo2[1];
Recogerá en un array cada uno de los trozos delimitados por los den
echo $trozo2[2];
separadores ser
echo $trozo2[3];
devuelt
echo $trozo2[4];
en trozos
echo $trozo2[5];
$trozo3=explode(" ",$a,3);
@print $trozo3[0]; Esta
Recogerá en un array cada uno de los trozos delimitados por los cadena
@print $trozo3[1];
separadores hasta un máximo de 3 sera devuelta en trozos
@print $trozo3[2];
@print $trozo3[3];
Anteponemos @ a print para evitar mensajes de error en los valores vacíos
@print $trozo3[4];
@print $trozo3[5];
$trozo4=explode("a",$a,3);
@print $trozo4[0]; Est
Recogerá en un array cada uno de los trozos delimitados por los c
@print $trozo4[1];
separadores hasta un máximo de 3 dena sera devuelta en trozos
@print $trozo4[2];
@print $trozo4[3];
Anteponemos @ a print para evitar mensajes de error en los valores vacíos
@print $trozo4[4];
@print $trozo4[5];
implode(" ",$trozo1) Esta cadena sera devuelta en trozos
implode("*",$trozo2) Est* c*den* ser* devuelt* en trozos
implode("-",$trozo3) Esta-cadena-sera devuelta en trozos
implode(":",$trozo4) Est: c:dena sera devuelta en trozos
join(" ",$trozo1) Esta cadena sera devuelta en trozos
join("*",$trozo2) Est* c*den* ser* devuelt* en trozos
join("-",$trozo3) Esta-cadena-sera devuelta en trozos
join(":",$trozo4) Est: c:dena sera devuelta en trozos
$cadena="Esta cadena será dividida con la función strtok"
Esta
$trocin = strtok ($cadena," "); cadena
será
while ($trocin) { dividida
echo "$trocin<br>"; con
$trocin = strtok (" "); la
} función
strtok
$trocin = strtok ($cadena," ");
echo $trocin,"<br>";
Esta
$trocin1 = strtok (" ");
cadena
echo $trocin1,"<br>";
Esta
$trocin2 = strtok (" ");
echo $trocin2,"<br>";

Pág. 85
Est
$trocin = strtok ($cadena,"a");
c
while ($trocin) {
den
echo "$trocin<br>";
será dividid
$trocin = strtok ("a");
con l
}
función strtok

Encriptación de cadenas

PHP dispone de funciones que permiten codificar o encriptar cadenas de caracteres.

bin2hex(cadena)

Devuelve una cadena ASCII que contiene la representación hexadecimal de la cadena. La conversión 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 parámetro de la función. 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 dimensión 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 ningún mecanismo inverso.

Seguramente habrás vivido esta experiencia. En muchos espacios de Internet –grupos de noticias, cuentas de
correo web, etcétera– que requieren un login y una contraseña cuando utilizas la opción de recuperar contraseñas no te
envían tu contraseña anterior, sino que te generan y envían una nueva.

Esto ocurre porque, por razones evidentes de seguridad, las contraseñas se almacenan usando estas huellas
digitales y resulta imposible recuperar los valores originales.

La única solución en estos casos es crear una nueva contraseña (suelen hacerlo con las funciones de números
aleatorios), enviarla de forma automática por correo electrónico y sustituir el valor anterior del registro de usuarios por el
resultado de la codificación md5 de la nueva contraseña.

crc32(cadena)

Aplica el algoritmo crc32 de comprobación de integridad y devuelve el valor del mismo. Se utiliza muchísimo en
los programas decompresión y descompresión de ficheros. Se aplica en el momento de comprimir y se incluye el valor
obtenido dentro del fichero comprimido. Después de la descompresión se vuelve a aplicar el mismo algoritmo y se
comparan ambos valores. La coincidencia será la garantía de que el fichero obtenido es idéntico al original.

Encriptaciones y codificaciones
Variable cadena Sintaxis Resultado
$a="Esta es la cadena" bin2hex($a) 45737461206573206c6120636164656e610a

Pág. 86
$a="Encriptame" crypt($a) $1$FyyNwU3P$egEZexjeVrYiH3ODukOy51
$a="Encriptame" crypt($a) $1$hEFXHKcC$9l2lbdI.YOOeRGNja2jKP.
$a="Encriptame" crypt($a,"zq") zqQ4qOeELzPFg
$a="Encriptame" crypt($a,"zq") zqQ4qOeELzPFg
$a="Encriptame" crypt($a,"@$") @$MB08wYjH9to
$a="Encriptame" md5($a) 67c3ca0aefda2595138168a85e7b33a0
$a="Encriptame" md5($a) 67c3ca0aefda2595138168a85e7b33a0
$a="Encriptame" crc32($a) 3166777410
Búsquedas y recuentos de caracteres
Variable cadena Sintaxis Resultado
$a="Contando caracteres" count_chars($a,0) Array
$b=count_chars($a,0);
$a="Contando caracteres" 3
echo $b[97];
$b=count_chars($a,0);
$a="Contando caracteres" 2
echo $b[ord("o")]
$a="Pepe Perez el perverso pecador en
substr_count($a,"Pe"); 2
penitencia"
$a="Pepe Perez el perverso pecador
substr_count($a,"pe"); 4
enpenitencia"

La función count_char($a,0) devuelve un array cuyos índices son los códigos ASCII de los caracteres y
cuyos valores son el número de veces que se repite cada uno de ellos.

La función substr_count($a,"cadena") determina el número de veces que aparece la cadena dentro de $a.
Diferencia entre mayúsculas y minúsculas.

Pág. 87
Etiquetas HTML

Dos interpretaciones

Recordemos que cuando un documento tiene extensión php es objeto de dos interpretaciones antes de ser
visualizado en el navegador. En primer lugar es PHP quien ejecuta sus scripts y devuelve al cliente el documento
resultante y, más tarde, será el propio navegador quien realice una segunda interpretación –del documento recibido– cuyo
resultado será la visualización de la página.

Cualquier salto de línea que se inserte en un documento será respetado por PHP y enviado al navegador, pero,
como éste solo entiende como tales sus propias etiquetas <br>, no serán visualizados, aunque sí estarán en el código
fuente de la página visualizada.

Hemos de considerar un nuevo concepto. PHP permite utilizar algunos caracteres especiales que son
transformados durante la ejecución del script. Uno de ellos –no es el único– es \n que es interpretado y convertido por el
intérprete de PHP en un salto de línea cuyo efecto será visible en el código fuente del documento enviado al navegador,
pero que –por no ser una etiqueta <br>– no producirá efecto alguno en la visualización de la página.

nl2br($A)

Esta función inserta de forma automática etiquetas HTML de salto de línea (<br>). Por cada salto de línea 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 minúsculas, sin comillas, y reemplazando, en el caso de que fuera necesario, los caracteres especiales por
un guión bajo _) de la página web cuya dirección (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 visualización y se impide que sean
interpretados como signos del lenguaje HTML.

htmlentities($a)

Es una función similar a la anterior, pero en este caso afecta a todos los caracteres que tienen equivalentes
como entidad HTMLutilizando el juego de carácteres 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 líneas
y hemos saltado de una a otra
pulsando enter";

$cadena2="Aquí\nseparamos\nlas\nlíneas\ncon\nsin\npulsar\nenter";

Pág. 88
$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 visualización
# 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 código fuente a través del navegador podrás observar como los resultados
del primer printgeneran saltos de línea en éste. Y en el caso del código correspondiente al segundo print, podrás visualizar
etiquetas <BR /> que son el resultado de la aplicación de la función nl2br

Las cadenas y las etiquetas HTML


Cadenas Sintaxis Resultado
Esto es
$a="Esto es\nun texto escrito\n en varias lineas\nsin un texto escrito
nl2br($a)
etiquetas<BR>"; en varias lineas
sin etiquetas<BR>
$dicc=array (
"Lundi"=>"Lunes",
Lunes es un dia bueno si hace
"good"=>"bueno", strtr($a,$dicc)
sol
"sun" =>"sol");
$a="Lundi es un dia good si hace sun"
$b=get_meta_tags($a); Programación, PHP, Apache,
$a="index.php"
echo $b['keywords'] MySQL
$b=get_meta_tags($a); Materiales para un curso a
$a="index.php"
echo $b['description'] distancia

$a="<H1>A</H1>" echo $a
A
echo
$a="<H1>A</H1>" <H1>A</H1>
htmlspecialchars($a)
La tabla de sustituciones de htmlspecialchars es esta:
Sustitye & por &amp;
" por &quot;
< por &lt;
> por &gt;

Pág. 89
Operadores bit a bit

Comentario previo

Incluimos la sintaxis de este tipo de operadores a título meramente informativo. Rara vez será necesario utilizarlos
en nuestras aplicaciones PHP. Su utilidad suele limitarse a la gestión de periféricos y algunas operaciones de cálculo de
carácter muy reiterativo en la que se puede conseguir un rendimiento muy superior a los operadores tradicionales.

En el ámbito propio del PHP pueden tener algún interés a la hora de elaborar rutinas para encriptar el código
fuente de algunos scripts que por su importancia pueden requerir ese tipo de protección. Los que sí han de resultarnos
de gran interés serán el resto de los operadores. Los iremos viendo en páginas sucesivas.

Operadores bit a bit

$A & $B

El operador & compara los valores binarios de cada uno de los bits de las cadenas $A y $B y devuelve 1 en el
caso que ambos sean 1, y 0 en cualquier otro caso.

Cuando las variables $A y $B son cadenas compara los valores binarios de los códigos ASCII de sus caracteres
y devuelve los caracteres ASCII correspondientes al resultado de esa comparación.

El operador &
Números Números como cadenas Cadenas alfanuméricas
Variables Valores binarios Variables Valores binarios Variables Valores binarios
$a=12 1100 $A="12" 110001110010 $A1="Rs" 10100101110011
$b=23 10111 $B="23" 110010110011 $B1="aZ" 11000011011010
$a&$b=4 100 $A&$B=02 110000110010 $A1&$B1=@R 10000001010010

En los casos de cadenas hemos diferenciado en rojo el valor binario correspondiente al primer carácter. Esos valores
binarios corresponden a la forma binaria del código ASCII de cada uno de los caracteres

Un caso de aplicación práctica podría se la determinación de la condición de par o impar de un número. El resultado
de una comparación $a & 1 significaría que si el valor asignado a $a fuera un número impar su forma binaria tendría como
último carácter (por la derecha) un uno. Por el contrario, si fuera par ese último carácter sería cero. Luego la comparación
mediante el operador & arrojaría 1 (coincidencia) en el primero caso y 0 (no coincidencia en el segundo). Si ejecutamos
este script: $a=13; print ($a & 1); veríamos que el resultado es 1 mientras que si hiciéramos lo mismo con $a=14; print ($a
& 1); resultaría 0. Sería una opción 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 número par).

$A | $B

Funciona de forma idéntica 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 |
Números Números como cadenas Cadenas alfanuméricas
Variables Valores binarios Variables Valores binarios Variables Valores binarios
$a=12 1100 $A="12" 110001110010 $A1="Rs" 10100101110011
$b=23 10111 $B="23" 110010110011 $B1="aZ" 11000011011010
$a|$b=31 11111 $A|$B=33 110011110011 $A1|$B1=s{ 11100111111011

Pág. 90
Puedes observar que el tratamiento es distinto cuando los mismos valores numéricos se asignan como entero y
como cadena. Al asignarlos como cadena opera los valores binarios de los códigos ASCII de los caracteres, mientras que
cuando se trata de números 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 ^
Números Números como cadenas Cadenas alfanuméricas
Valores Valores
Variables Variables Variables Valores binarios
binarios binarios
$a=12 1100 $A="12" 110001110010 $A1="Rs" 10100101110011
$b=23 10111 $B="23" 110010110011 $B1="aZ" 11000011011010
$a^$b=27 11011 $A^$B= 000011000001 $A1^$B1=3) 01100110101001

$A << $B

Realiza la operación $A * 2$B. Hace el cálculo añadiendo $B CEROS (binarios) a la derecha de la cadena binaria
$A.

El operador <<
Números Números como cadenas Cadenas alfanuméricas
Variables Valores binarios Variables Valores binarios Variables Valores binarios
$a=12 1100 $A="12" 110001110010 $A1="Rs" 10100101110011
$b=2 10 $B=2 10 $B1=2 10
$a<<b=48 110000 $A<<$B=48 110000 $A1<<$B1=0

El operador << multiplica el valor de la primera cadena por 2 elevado al valor de la segunda. Al ser un
operador matemático solo tiene sentido cuando ambas variables son números naturales. En las cadenas alfanuméricas
extrae los números que pudiera haber al comienzoy, en caso de no haberlos, toma valor cero.

$A >> $B

Divide el valor $A entre 2$B. Hace la operación en la cadena binaria quitando $B CEROS (por la derecha) de la
cadena $A.

El operador >>
Números Números como cadenas Cadenas alfanuméricas
Variables Valores binarios Variables Valores binarios Variables Valores binarios
$a=12 1100 $A="12" 110001110010 $A1="Rs" 10100101110011
$b=2 10 $B=2 10 $B1=2 10
$a>>b=3 11 $A>>$B=3 11 $A1>>$B1=0

Para este operador (>>) son aplicables los mismos comentarios hechos en el párrafo 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

Pág. 91
Operadores de comparación

Antes de empezar

Si es este tu primer contacto con el mundo de la programación es probable que estés 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 página y las siguientes van a ser básicas para el éxito en ese lógico y razonable afán utilitarista. Pensemos
en nuestro día a día. 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 más prudente será empezar


por comparar las características (potencia, diseño, precio, etc.) de los diferentes modelos. Salvo en casos excepcionales,
no tomaríamos una decisión de compra a través de un solo parámetro sino que haríamos una evaluación conjunta de
todos esos factores (menos potencia pero mejor precio y diseño muy similar, por citar un ejemplo) y sería a través de esa
evaluación como optaríamos por una marca o modelo.

Una vez ejercida la opción –y no antes– sería el momento de realizar la compra del nuevo coche. PHP, y en
general todos los lenguajes de programación, disponen de herramientas que permiten emular cada uno de esos procesos
de la conducta humana. Los iremos viendo en esta página y en las siguientes.

Operadores de comparación

PHP dispone de los siguientes operadores de comparación:

$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 –carácter ASCII 0– (FALSO) cuando son distintas.

Mediante este operador se pueden comparar variables de distinto tipo. Para comparar una cadena con
un número se extrae el valor entero de la cadena (si lleva dígitos al comienzo los extrae y en caso contrario le asigna el
valor cero) y utiliza ese valor para hacer la comparación.

Cuando se comparan cadenas discrimina entre mayúsculas y minúsculas ya que utiliza los códigos ASCII de cada
uno de los caracteres para hacer la comparación que se hace de izquierda a derecha y devuelve 1 (CIERTO) sólo en el
caso que coincidan exactamente los contenidos de ambas cadenas.

El operador ==
A B Operador Sintaxis Resultado
$A=123 $B=123 == $A==$B 1
$A=123.0 $B=123 == $A==$B 1
$A=123 $B="123" == $A==$B 1
$A=123 $B="123ABC" == $A==$B 1
$A=123 $B=124 == $A==$B
$A=123 $B=124 == ord($A==$B) 0
$A="abc" $B="ABC" == $A==$B
$A="abc" $B="abc" == $A==$B 1
$A="abc" $B="abcd" == $A==$B

Los valores de la columna señalada como Resultados se obtienen mediante la función 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 (código ASCII 0) y ese carácter
carece de símbolo gráfico.
Hemos marcado en rojo una excepción.
En ese caso, la instrucción es echo ord($A==$B); y –como recordarás– dado que ord, que devuelve el código ASCII
del caracter contenido en el paréntesis que le acompaña, podemos comprobar a través del cero de este resultado, que,
efectivamente, la no coincidencia devuelve NUL.

Pág. 92
$A === $B

El operador === es similar al anterior, pero realiza la comparación en sentido estricto. Para que devuelva 1 es
necesario que sean iguales los valores de las variables y también su tipo.

El operador ===
A B Operador Sintaxis Resultado
$A=123 $B=123 === $A===$B 1
$A=123.0 $B=123 === $A===$B
$A=123 $B="123" === $A===$B
$A=123 $B="123ABC" === $A===$B
$A=123 $B=124 === $A===$B
$A=123 $B=124 === ord($A===$B) 0
$A="abc" $B="ABC" === $A===$B
$A="abc" $B="abc" === $A===$B 1
$A="abc" $B="abcd" === $A===$B

Observa que los valores señalados en rojo –a diferencia de lo que ocurre con el operador anterior– devuelvenNUL como
resultado.
En este caso no sólo compara valores sino que también compara tipos de variables. Al ser una de ellas tipo numérico y
la otra cadena alfanumérica 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 negación, en este
caso podríamos leer«no 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 B Operador Sintaxis Resultado
$A=123 $B=123 != $A!=$B
$A=123.0 $B=123 != $A!=$B
$A=123 $B="123" != $A!=$B
$A=123 $B="123ABC" != $A!=$B
$A=123 $B=124 != $A!=$B 1
$A=123 $B=124 != ord($A!=$B) 49
$A="abc" $B="ABC" != $A!=$B 1
$A="abc" $B="abc" != $A!=$B
$A="abc" $B="abcd" != $A!=$B 1

En los ejemplos señalados en rojo Puedes comprobar el carácter 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 comparación son los siguientes:

 – Los valores numéricos siguen el criterio matemático.

Pág. 93
 – Cuando se trata de un número y una cadena extrae el valor numérico de ésta (cero si no hay ningún dígito al principio
de la misma) y hace una comparación matemática.
 – En el supuesto de dos cadenas, compara uno a uno –de izquierda a derecha– los códigos ASCII de cada uno de los
carácteres (primero con primero, segundo con segundo, etcétera). Si al hacer esta comprobación encuentra –en la primera
cadena– un caracter cuyo código 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 comparación) que los caracteres que faltan en
la cadena más corta son NUL (ASCII 0).

El operador <
A B Operador Sintaxis Resultado
$A=123 $B=123 < $A<$B
$A=123 $B="123" < $A<$B
$A=123.0 $B="123" < $A<$B
$A=123 $B="123ABC" < $A<$B
$A=123 $B=124 < $A<$B 1
$A=123 $B=124 < ord($A<$B) 49
$A="abc" $B="ABC" < $A<$B
$A="abc" $B="abc" < $A<$B
$A=" bcd" $B="abcd" < $A<$B 1
$A="aacd" $B="abcd" < $A<$B 1
$A="abc" $B="abcd" < $A<$B 1
$A="abcd" $B="abc" < $A<$B
$A="A" $B="a" < $A<$B 1
$A="a" $B="A" < $A<$B
$A="aBC" $B="A" < $A<$B
$A="123" $B=124 < $A<$B 1
$A=123 $B="124" < $A<$B 1

Observa los ejemplos señalados en rojo. Cuando las cadenas tienen distinta longitud este operador considera que los
caracteres que faltan en la cadena más corta son NUL. Esa es la razón 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 idéntica al anterior. La única diferencia es que ahora aceptará como ciertos los casos
de igualdad tanto en el caso de números como en el de códigos ASCII.

El operador <=
A B Operador Sintaxis Resultado
$A=123 $B=123 <= $A<=$B 1
$A=123.0 $B=123 <= $A<=$B 1
$A=123 $B="123" <= $A<=$B 1
$A=123 $B="123ABC" <= $A<=$B 1
$A=123 $B=124 <= $A<=$B 1
$A=123 $B=124 <= ord($A<=$B) 49
$A="abc" $B="ABC" <= $A<=$B
$A="abc" $B="abc" <= $A<=$B 1
$A="abc" $B="abcd" <= $A<=$B 1
$A="A" $B="a" <= $A<=$B 1
$A="a" $B="A" <= $A<=$B
$A="aBC" $B="A" <= $A<=$B
$A="123" $B=124 <= $A<=$B 1
$A=123 $B="124" <= $A<=$B 1

Pág. 94
Hemos modificado la instrucción marcada en rojo para comprobar el código ASCII de caracter que devuelve, en el caso
de ser cierto, el resultado de la comparación. El valor que aparece (49) como resultado es el código ASCII del carácter 1.

$A > $B

Es idéntico –en el modo de funcionamiento– a $A < $B. Solo difiere de éste en el criterio de comparación que
ahora requerirá que los valores de $A sean mayores que los de la variable $B.

El operador >
A B Operador Sintaxis Resultado
$A=123 $B=123 > $A>$B
$A=123 $B="123" > $A>$B
$A=123 $B="123ABC" > $A>$B
$A=123 $B=124 > $A>$B
$A=123 $B=124 > ord($A>$B) 0
$A="abc" $B="ABC" > $A>$B 1
$A="abc" $B="abc" > $A>$B
$A="abc" $B="abcd" > $A>$B
$A="A" $B="a" > $A>$B
$A="a" $B="A" > $A>$B 1
$A="aBC" $B="A" > $A>$B 1
$A="123" $B=124 > $A>$B
$A=123 $B="124" > $A>$B

$A >= $B

Añade al anterior la posibilidad de certeza en caso de igualdad.

El operador >=
A B Operador Sintaxis Resultado
$A=123 $B=123 >= $A>=$B 1
$A=123 $B="123" >= $A>=$B 1
$A=123 $B="123ABC" >= $A>=$B 1
$A=123 $B=124 >= $A>=$B
$A=123 $B=124 >= ord($A>=$B) 0
$A="abc" $B="ABC" >= $A>=$B 1
$A="abc" $B="abc" >= $A>=$B 1
$A="abc" $B="abcd" >= $A>=$B
$A="A" $B="a" >= $A>=$B
$A="a" $B="A" >= $A>=$B 1
$A="aBC" $B="A" >= $A>=$B 1
$A="123" $B=124 >= $A>=$B
$A=123 $B="124" >= $A>=$B

Pág. 95
Operadores lógicos

Operadores lógicos

Mediante operadores lógicos es posible evaluar un conjunto de variables lógicas, es decir, aquellas cuyos valores
sean únicamente: VERDADERO o FALSO (1 ó NUL). El resultado de esa evaluación será siempre 1 ó NUL.

$A AND $B

El operador AND devuelve VERDADERO (1) en el caso de que todas las variables lógicas comparadas sean
verdaderas, y FALSO (NUL) cuando alguna de ellas sea falsa.

El operador AND
Variables $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas"
$x=$a>$b;$y=$a>$c;$z=$a>$f;
Ejemplo de sintaxis
echo ($x AND $y AND $z);
Otra sintaxis echo ($a>$b AND $a>$c AND $a>$f);
Condición A Condición B Condición C A B C Resultado
$a>$b $a>$c $a>$f 1 1 1 1
$a>$b $a>$c $a<$f 1 1
$a>$b $a<$c $a>$f 1 1
$a<$b $a>$c $a>$f 1 1
$a<$b $a<$c $a>$f 1
$a<$b $a>$c $a<$f 1
$a>$b $a<$c $a<$f 1
$a<$b $a<$c $a<$f

$A && $B

El operador && se comporta de forma idéntica al operador AND. La única diferencia entre ambos es que operan
con distinta precedencia. Más abajo veremos el orden de precedencia de los distintos operadores.

El operador &&
Variables $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas"
Condición A Condición B Condición C A B C Resultado
$a>$b $a>$c $a>$f 1 1 1 1
$a>$b $a>$c $a<$f 1 1
$a>$b $a<$c $a>$f 1 1
$a<$b $a>$c $a>$f 1 1
$a<$b $a<$c $a>$f 1
$a<$b $a>$c $a<$f 1
$a>$b $a<$c $a<$f 1
$a<$b $a<$c $a<$f

$A OR $B

Para que el operador OR devuelva VERDADERO (1) es suficiente que una sola de las variables lógicas
comparadas sea verdadera. Únicamente devolverá FALSO (NUL) cuando todas ellas sean FALSAS.

El operador OR
Variables $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas"
Condición A Condición B Condición C A B C Resultado

Pág. 96
$a>$b $a>$c $a>$f 1 1 1 1
$a>$b $a>$c $a<$f 1 1 1
$a>$b $a<$c $a>$f 1 1 1
$a<$b $a>$c $a>$f 1 1 1
$a<$b $a<$c $a>$f 1 1
$a<$b $a>$c $a<$f 1 1
$a>$b $a<$c $a<$f 1 1
$a<$b $a<$c $a<$f

$A || $B

El operador || se comporta de forma idéntica al operador OR. Su única diferencia es el orden de precedencia con
el que opera.

El operador ||
Variables $a=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas"
Condición A Condición B Condición C A B C Resultado
$a>$b $a>$c $a>$f 1 1 1 1
$a>$b $a>$c $a<$f 1 1 1
$a>$b $a<$c $a>$f 1 1 1
$a<$b $a>$c $a>$f 1 1 1
$a<$b $a<$c $a>$f 1 1
$a<$b $a>$c $a<$f 1 1
$a>$b $a<$c $a<$f 1 1
$a<$b $a<$c $a<$f

$A XOR $B

El operador XOR devuelve VERDADERO (1) sólo 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=32; $b=0; $c=-7; $d=4.32; $f="23 Ptas"
Condición A Condición B A B Resultado

$a>$b $a>$c 1 1

$a>$b $a<$c 1 1

$a<$b $a>$c 1 1

$a<$b $a<$c

! $A

Este operador NOT (negación) devuelve VERDADERO (1) si la variable lógica $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 lógicos sería necesario que $A y $B contuvieran valores lógicos,
y eso requeriría un paso previo para asignarles valores de ese tipo. Habría que recurrir a procesos de este tipo:

Pág. 97
$A = $x>$y;
$B= $x >=$z;
$A && $B;

pero se obtendría el mismo resultado escribiendo:

$x>$y && $x >=$z;

que, aparte de ser la forma habitual de hacerlo, nos evita dos líneas de instrucciones. Aunque el propio ejemplo
se auto comenta, digamos que al utilizar operadores lógicos se pueden sustituir las variables lógicas por expresiones que
den como resultado ese tipo de valores.

Orden de precedencia

Cuando se usan los operadores lógicos se plantean situaciones similares a lo que ocurre con las operaciones
aritméticas. Dado que permiten trabajar con secuencias de operaciones sería posible, por ejemplo, una operación de este
tipo:

$a<$b OR $c<$b && $a<3

Surgirían preguntas con estas:

 – ¿qué comparación se haría primero OR ó &&?


 – ¿se harían las comparaciones en el orden natural?
 – ¿alguno de los operadores tiene prioridad sobre el otro?

Igual que en las matemáticas, también aquí, hay un orden de prioridad que es el
siguiente: NOT, &&, ||, AND, XOR y, por último, OR.

De esta forma la operación && se realizaría antes que ||, mientras que si pusiéramos AND en vez de && sería la
operación || la que se haría antes y, por lo tanto, los resultados podrían variar de un caso a otro.

Aquí también es posible, de la misma manera que en la aritmética, utilizar paréntesis para priorizar una operación
frente a otra.

Es muy importante prestar atención a la construcción correcta de estas estructuras. Un descuido en la atención 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 fácilmente este tipo de errores de
programación. 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 paréntesis y los criterios de prioridad de los distintos operadores contenidos
en la estructura lógica.

<?php
# asignemos valores a cuatro variables
$a=3;
$b=6;
$c=9;
$d=17;
# utilicemos operadores de comparación
# y recojamos sus resultados en nuevas variables
$x= $a<$b;
$y= $a<$b;
$z=$c>$b;
# apliquemos un operador lógico (por ejemplo &&)
# e imprimamos el resultado
Pág. 98
print("Resultado FALSO si no sale nada: ".($y && $z)."<br>");
# hagamos la misma comparación 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é ocurriría si escribíeramos
$a
<$b OR $c>
$b && $d<$a ?
El operador && tiene preferencia ante OR,
luego haría primero la comparación $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 opción 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 adelántemosla un poco...
si el contenido del paréntesis que va detrás del if es cierto
imprimirá cierto y en caso contrario imprimirá falso
Aqui debería 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 paréntesis nos devolverá a la situación anterior
# escribamos $a<$b || ($c>$b AND $d<$a)
# veremos que el resultado es CIERTO como ocurría en el primer caso

if($a<$b || ($c>$b AND $d<$a)) {


print "cierto<br>";
}else{
print "falso<br>";
}
?>

ejemplo40.php

Pág. 99
Operadores de incremento

Operadores de incremento

Los caracteres ++ y -- escritos al lado del nombre de una variable producen incrementos o decrementos de una
unidad en el valor de la misma. De igual forma, los operadores +=n y -=n escritos a la derecha del nombre de una variable
producen incrementos o decrementos de nunidades en el valor de la variable.

Como veremos a continuación, los operadores ++ y -- se comportan de distinta forma según estén situados a
la izquierda o a laderecha de la variable.

Estas operaciones sólo tienen sentido en variables numéricas –enteras o no–, pero si se aplican a variables
de cadena les asignan previamente valor cero, salvo en una curiosa excepción que puedes ver en la primera de las tablas
que tienes aquí a la derecha.

Operadores de pre incremento

++$A y --$A

Este operador incrementa el valor de la variable en una unidad (+1 o -1) antes de ejecutar el contenido de la
instrucción.

El operador ++$A
Variables numéricas Variables alfanuméricas
Valor inicial Sintaxis Resultado Valor inicial Sintaxis Resultado
$a=23 echo ++$a 24 $b="pepe" echo ++$b pepf
$a=23 echo ++$a*2 48 $b="pepe" echo ++$b*2 0

El operador ––$A
Variables numéricas Variables alfanuméricas
Valor inicial Sintaxis Resultado Valor inicial Sintaxis Resultado
$a=23 echo ––$a 22 $b="pepe" echo --$b pepe
$a=23 echo --$a*2 44 $b="pepe" echo ––$b*2 0

$A+=n y $A-=n

Este operador incrementa el valor de la variable en n unidades (+n o -n) y luego ejecuta el contenido de la
instrucción.

El operador $A +=n
Variables numéricas Variables alfanuméricas
Valor inicial Sintaxis Resultado Valor inicial Sintaxis Resultado
echo $a+=5; 28 echo $b+=5; 5
$a=23 $b="pepe"
echo $a 28 echo $b 5
echo 2*$a+=5; 56 echo 2*$b+=5; 10
$a=23 $b="pepe"
echo 2*$a 56 echo 2*$b 10

El operador $A –=n
Variables numéricas Variables alfanuméricas
Valor inicial Sintaxis Resultado Valor inicial Sintaxis Resultado
echo $a-=5; 18 echo $b-=5; -5
$a=23 $b="pepe"
echo $a 18 echo $b -5

Pág. 100
echo 2*$a-=5; 36 echo 2*$b-=5; -10
$a=23 $b="pepe"
echo 2*$a 36 echo 2*$b -10

Operadores de post incremento

$A++ y $A--

Cuando los operadores ++ o -- están situados a la derecha de la variable los incrementos no se producen hasta
que se ejecute lainstrucción siguiente.

El operador $A++
Valor inicial de la variable Sintaxis Resultado
echo $a++; 23
$a=23
echo $a 24
echo 2*$a++; 46
$a=23
echo 2*$a 48

El operador $A--
Valor inicial de la variable Sintaxis Resultado
echo $a--; 23
$a=23
echo $a 22
echo 2*$a--; 46
$a=23
echo 2*$a 44

Pág. 101
Operadores condicionales

Operadores condicionales

Este tipo de operadores son el auténtico cerebro de cualquier aplicación que desarrollemos en PHP o en cualquier
otro lenguaje de programación. Los operadores condicionales son la herramienta que permite tomar decisiones tales
como: hacer o no hacer, y también: hacer algo bajo determinadas condiciones y otra cosa distinta en caso de que no se
cumplan.

Aunque para simplificar los ejemplos vamos a utilizar en ellos una sola condición, este operador permite incluir
como tal cualquier estructura lógica, del tipo que hemos visto en la página anterior, por compleja que esta sea.

Alternativas de sintaxis

Como iremos viendo a lo largo de estas líneas, este operador permite diferentes formas de sintaxis que podemos
utilizar según nuestra conveniencia. La forma más simple es:

if(condición) ..instrucción... ;

Si se cumple la condición establecida en el paréntesis se ejecutará la primera instrucción que se incluya a


continuación de ella. Cualquier otra instrucción que hubiera después de ella no se vería afectada por el condicional
ejecutándose en cualquier circunstancia.

<?php
# Definamos dos variables y asignémosles valores.
# Hubieran podido obteners por cualquier otro procedimiento:
# desde un array,
# a través de un formulario cuya action ejecute este script, etc.

$A=3; $B="3";
if ($A==$B)
print ("A es igual B");

# cualquier otra instrucción que incluyéramos de aquí


# en adelante se ejecutaría independientemente de que la condición
# se cumpla o no ya que esta forma de if (sin llaves)
# únicamente considera la primera instrucción
# comprobémoslo 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 instrucción. No la condicionará el if");
?>

ejemplo41.php
if(condición){
..instrucción 1... ;
..instrucción 2... ;
.... ;
}

Es una ampliación del caso anterior. Cuando es necesario que –en caso de que se cumpla la condición o
condiciones– se ejecute más de una instrucción, se añade una { para indicar que habrá varias instrucciones, se escriben
estas y se señala el final mediante }.

if(condición) :
..instrucción 1... ;
..instrucción 2... ;
Pág. 102
.... ;
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 porendif

<?php
$A=3; $B="3";
# en este caso cerraremos entre llaves las líneas
# que deben ejecutarse si se cumple la condición

if ($A==$B){
print ("A es igual B");
echo "<br>";
echo "Este if tiene varias instrucciones contenidas entre llaves";
}
# una sintaxis alternativa a las llaves
# sustituyamos la { por : y la } por endif
if ($A==$B):
print ("A es igual B");
echo "<br>";
echo "Hemos cambiado {} por : endif";
endif;
?>

ejemplo42.php

if(condicion){ ?>
..Etiquetas HTML... ;
..HTML... ;
.... ;
<? } ?>

PHP permite la utilización del operador condicional if con esta sintaxis. Un primer script PHP establece la
condición. Todo lo contenido entre ese primer script y el de cierre: <?}?> será código HTML (está fuera del script), que
se insertará en el documento sólo en el caso de que se cumpla la condición.

if(condicion) : ?>
..Etiquetas HTML... ;
..HTML... ;
.... ;
<? endif; ?>

Idéntica a la anterior, con la sintaxis : y endif.

<?php
$a=5;
# observa que ponemos la etiqueta de fin de script
# después 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 línea siguiente a este comentario


volveremos a PHP para insertar la llave que indica el fin del if //-->
<? } ?>

<?
Pág. 103
# 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 línea 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 ampliación. En conjunción con else permite añadir
instrucciones que sólo serían ejecutadas en caso de no cumplirse la condición. Esta nueva opción se habilita mediante
la siguiente sintaxis:

if(condicion){
... instrucciones a ejecutar cuando se cumple la condición
} else {
... instrucciones a ejecutar cuando NO se cumple la condición
}

<?php
$A=3; $B="4";
if ($A==$B){
#estas instrucciones se ejecutarían si se cumple la condición
print ("A es igual B");
echo "<br>";
echo "Este if tiene varias intrucciones";
}else{
# estas se ejecutarían 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 también la sintaxis alternativa :, endif, aunque en este caso hay que hacer una precisión -puedes verla
aquí debajo– la llave de cierre que iba delante de else se elimina y no es sustituida por ningún caracter ni símbolo especial.

<?if(condicion): ?>
... código HTML a incluir cuando se cumple la condición
<? else: ?>
... codigo HTML a incluir cuando NO se cumple la condición
<? endif; ?>

<?php
$a=3;
# observa que ponemos la etiqueta de fin de script
# después 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>

Pág. 104
<!-- en la línea siguiente a este comentario
volveremos a PHP para insertar el else seguido de dos puntos
y cerramos de nuevo el script con ?>//-->
<? else: ?>

<!-- Aquí más HTML para el (else)


caso de que no se cumpla la condición //-->
<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 cómodo el uso de esta otra posibilidad de sintaxis conocida como operador
condicional ternario

(condición) ? (opcion1) : (opcion2)

Si se cumple la condición se ejecuta la opcion1. En el caso de que no se cumpla se ejecutará la opcion2.

<?php $a=5;
($a==8) ? ($B="El valor de a es 8"): ($B="El valor de a no es 8");
echo $B;
?>

Ejemplo con a=8 Ejemplo con a=5

If ... elseif .. else

Otra posibilidad dentro de la estructura de los operadores condicionales es la inclusión de elseif. Esta es la
sintaxis. Dentro del ejemplo tienes los comentarios explicativos.

if(condicion1){
... instrucciones a ejecutar cuando se cumple la condición1
}elseif(condicion2){
... instrucciones a ejecutar cuando se cumple la condición2 sin cumplirse condición1
} else {
... instrucciones a ejecutar cuando NO se cumple ni la condición1 ni la condicion2
}

<?php $a=1;
if ($a==1){
echo "El valor de la variable A es 1";
}elseif ($a==2){
echo "El valor de la variable A es 2";
}elseif ($a==3){
echo "El valor de la variable A es 3";
}else{
echo "La variable A no es 1, ni 2, ni 3";
}
?>

Ejemplo con a=3 Ejemplo con a=-7


<?php $a=1;
Pág. 105
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 paréntesis dentro de paréntesis en las matemáticas. Y este
operador lo permite, con una única condición, que verás en esta muestra de sintaxis.

if(condición1){
... instrucciones para le caso de que se cumpla la condición1....
if(condición2){
... 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 opción else marcada en marrón.
Es obligatorio que así sea. De igual forma, podríamos insertar bloques sucesivos hasta llegar a crear una estructura tan
amplia como fuera necesaria. Como ves, todo un mundo de posibilidades.

La función exit()

PHP dispone de una función exit() muy útil a los efectos del comentario anterior. Cuando se
ejecuta exit() se interrumpe la ejecución del script con lo que la respuesta del servidor a la petición del cliente incluirá
únicamente los contenidos generados antes de su ejecución.

Pág. 106
La función switch

La función switch

Una alternativa al uso de condicionales del tipo if es la función switch. Se trata de un condicional que evalúa una
variable y, según su valor, ejecuta unas instrucciones u otras. Su sintaxis es la siguiente:

switch ( variable ) {
case n1:
...instrucciones a ejecutar en el caso de que la variable sea igual a n1...
case n2:
..instrucciones a ejecutar en el caso de que la variable sea igual a n2...
}

Cuando se usa esta sintaxis se ejecutan todas aquellas instrucciones que han sido incluidas a partir de la etiqueta
en la que el valor que sigue a case coincide con el valor de la variable. Es decir, si en la expresión anterior la variable es
igual a n1 se ejecutarían todas las instrucciones, tanto las que van detrás de case n1 como las que van detrás de case n2.

La forma más habitual de uso de esta función es esta:

switch ( variable ) {
case n1:
...instrucciones a ejecutar en el caso de que la variable sea igual a n1...
break;
case n2:
..instrucciones a ejecutar en el caso de que la variable sea igual a n2...
break;
}

Esta opción incluye antes de cada nuevo case la función de ruptura break. Cuando PHP encuentra
el break interrumpe la ejecución yno la reanuda hasta la instrucción siguiente a la } que cierra el switch.
Insertando break en cada una de las opciones case, sólo se ejecutarían las instrucciones contenidas entre case num y
ese break.

default:

Bajo este nombre (default:) se pueden incluir dentro de la función switch un conjunto de instrucciones que solo
serán ejecutadas en el caso de que el valor de la variable no coincida con ninguno de los case. Su comportamiento es
equivalente a else en el condicional if.

Ejemplos con switch

<?php
# esta es la variable que controlará la función switch
$i=1;

switch ($i) {

#insertamos la etiqueta case 0 y a continuación


# las instrucciones correspondientes

case 0:
print "i es igual a 0 - No he puesto el break<br>";

# insertamos la etiqueta case 1 y a continuación


# las instrucciones correspondientes
# como no hemos puesto break y en este ejemplo $i=1
# se ejecutarán todas las instrucciones escritas
# de aquí en adelante

Pág. 107
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 ejecutarán
# 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

Pág. 108
Bucles while

Los bucles

La necesidad de repetir la ejecución de instrucciones es algo habitual en el mundo de la programación. Frente a


la alternativa –poco práctica– de reescribir las instrucciones todos los lenguajes de programación disponen de funciones
que pueden ejecutar un bloque de instrucciones de forma repetitiva.

La instrucción while

Como ocurría en el caso de if, el parámetro condición permite cualquier estructura lógica, y también dispone de
distintas opciones de sintaxis.

while(condición)
...instrucción que se ejecutará mientras se cumpla la condición

Con esta sintaxis estaremos indicando que la instrucción siguiente (sólo una instrucción) ha de ejecutarse continua
y repetidamente hasta que deje de cumplirse la condición establecida.

<?php
# asignemos un valor a la variable $A
$A=0;
/* establezcamos la condición menor que cinco
e insertemos dentro de la instrucción algo que modifique
el valor de esa variable de modo que en algún momento
deje de cumplirse la condición;
de no ocurrir esto, el bucle se repetiría indefinidamente
en este ejemplo el autoincremento ++ de la variable
hará que vaya modificándose su valor*/

while ($A<5) echo "El valor de A es: ",$A++,"<br>";


# comprobemos que este while solo ejecuta una instrucción
# la delimitada por el punto y coma anterior
print("Esto solo aparecerá una vez. While no lo incluye en su bucle");
?>

ejemplo55.php

while(condición) {
...instrucción que se ejecutará mientras se cumpla la condición...
....otra ...instrucción que se ejecutará mientras se cumpla la condición...
..........
}

De forma similar a la utilizada en el caso de if, también en este caso, las llaves hacen la función de contenedores de
las instrucciones cuya ejecución debe repetirse mientras se cumpla la condición.

<?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;
Pág. 109
# esta instrucción es importantísima
# si no modificamos el valor de $A el bucle sería infinito
$A++;
print("</td></tr>");
}
# cerremos la etiqueta table
print "</table>";
?>

ejemplo56.php

while(condición) :
...instrucción que se ejecutará mientras se cumpla la condición...
....otra ...instrucción que se ejecutará mientras se cumpla la condición...
..........
endwhile;

También aquí se mantiene la similitud con la sintaxis del condicional if. La llave ({) pueden sustituirse por (:) y en
este caso en vez de (}) habría 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 condición 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 próxima fila
ya que el bucle (magenta) va reduciendo ese valor a cero
y en caso de no restaurar el viejo valor no volvería a ejecutarse
ya que no cumple la condición 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 continuación un nuevo ejemplo en el hemos hecho una ligera modificación del anterior incluyendo un
condicional if. No incluimos aquí el código fuente para evitarte la monotonía de repetir íntegramente y con ligeras
modificaciones el supuesto anterior. Utilizaremos un nuevo recurso de visualización tal como puedes comprobar si pulsas
en el enlace Ver código fuente. Esta opción utiliza la función

Pág. 110
show_source('pagina');

que permite visualizar el código fuente del documento que se indica en el parámetro 'pagina'. Es muy útil para
nuestros propósitos pero presenta un problema de seguridad. Si escribes –en el parámetro pag– la dirección completa
de una web cualquiera (que tenga extensiónphp) 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 58

while(condición) : ?>
...etiquetas HTML que se insertarían repetidamente mientras se cumpla la condición
.....
<? endwhile; ?>

También while permite cerrar el script PHP después de (:) o de la sintaxis alternativa ({) e insertar etiquetas HTML,
indicando más tarde el final del bucle con <? } ?> o <? endwhile; ?>, según proceda.

Whiles anidados

Una nueva similitud sintáctica con if. En el caso de while también es posible insertar un while dentro de otro while
utilizando una sintaxis de este tipo:

while(condición1):
...instrucción
while(condición2) {
...instrucción
.....
}
.....
endwhile;

En esta descripción 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 anidación no limita un ápice las posibilidades de la
sintaxis.

Pág. 111
Bucles do ... while

El bucle do... while

Estamos ante una variante del bucle while que hemos visto en la página anterior. La sintaxis es la siguiente:

do {
.... instrucción 1...
.... instruccion2...
} while(condición) ;

Se diferencia de while en que en este caso se comprueba la condición después 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 ejecutarían una vez. Respecto a la sintaxis, como puedes
observar, detrás de do se inserta una llave ({) que señala el comienzo de las instrucciones pertenecientes al bucle. El
final de esas instrucciones lo señala la otra llave (}) que precede a while(condición).

break

La función break –de forma similar a lo que ocurría en el caso de switch– permite interrumpir la ejecución de
bucle. Tal como puede verse en el ejemplo, podría –entre otras posibilidades– utilizarse para evitar la primera ejecución
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 página anterior pero break se comporta en el caso de while de forma idéntica a la
descrita aquí.

<?php
$A=0;
do {
++$A;
echo "Valores de A usando el do: ",$A,"<br>";
} while($A<5);
$B=7;
do {
echo "Pese a que B es mayor que 5 se ejecuta una vez. B= ",$B,"<br>";
} while($B<5);
?>

ejemplo59.php
<?php
$A=500;
do {
if ($A>=500) {
echo "No puede ejecutarse el bucle, porque no se cumple la condicion";
break;
}
++$A;
echo "Valores de A usando el do: ",$A,"<br>";

} while($A<500);
echo "<BR>He salido del bucle porque A es: ",$A;
?>

ejemplo60.php

Pág. 112
El ejemplo que tienes aquí debajo es similar al ejemplo n.º 57 de la página anterior. Sólo hemos sustituido los
bucles while que allí habíamos utilizado por otros del tipo do ... while.

ejemplo61.php

Pág. 113
Bucles for

El bucle for

Se trata de una nueva forma –de uso bastante habitual– que permite establecer un bucle que se repetirá mientras
una variable numérica se mantenga dentro de intervalo –especificado en la sintaxis del propio bucle– indicándose también
en la propia instrucción el criterio de modificación de esa variable en cada ejecución del bucle. La sintaxis es la siguiente:

for ( desde ; hasta ; incremento ){


.........
...instrucciones....
.........
}

El parámetro desde permite asignar un valor inicial a una variable ($var=num) que hará funciones de controladora
de iteraciones. El parámetro hasta establece la condición que limita el valor máximo que puede alcanzar la variable
de control y el parámetro incremento (con una sintaxis del tipo $variable++; $variable--; ++$variable; --$variable; $variable
+=n o $variable -=n establece los incrementos o decrementosde la variable controladora en cada iteración del bucle.

Las instrucciones contenidas entre { } serán ejecutadas cada vez que se reitere el bucle.

<?php
for ($i = 1; $i <= 10; $i++) {
print $i."<br>";
}
?>

ejemplo62.php

Variantes del bucle for

El bucle for permite algunas variantes respecto a su forma más general. Son estas:

for ( desde ; ; incremento ){


.........
...instrucciones....
.........
}

En este caso se omite el valor del parámetro hasta (observa que no se omite el separador de parámetros (;) con
lo que en realidad se está asignando a hasta el valor NUL.

Cuando se utiliza esta sintaxis, el bucle se repetiría de forma indefinida (la variable podría 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 opción de ruptura del bucle -el famoso break que ya hemos visto al estudiar la instrucción while y
otras anteriores–.

<?php
for ($i = 1;;$i++) {
if ($i > 10) {
break;
}
print $i."<br>";
}
?>

ejemplo63.php

Pág. 114
for ( ; ; ){
.........
...instrucciones....
.........
}

En este caso no se inserta ningún parámetro pero si se escriben los ; delimitadores de los mismos. Si observas el
ejemplo verás que el control se realiza fuera del for. El valor de la variable contador se asigna fuera del bucle, los
incrementos de esa variable están escritos en las líneas de instrucciones y llevan un operador condicional con la
función break para permitir la salida.

<?php
$i = 1;
for (;;) {
if ($i > 10) {
break;
}
print $i."<br>";
$i++;
}
?>

ejemplo64.php

for( desde ; hasta ; instrucciones, incremento )

Esta nueva variante de for permite insertar instrucciones a través del tercer parámetro de la función. Si insertamos
como tercer parámetro un conjunto de instrucciones, separadas por comas, se ejecutarán de igual forma que si
estuvieran contenidas entre { y }

En este caso, el modificador de la variable de control (incremento) se incluye como una instrucción más –separada
por una coma– de las contenidas en ese tercer parámetro de la función.

<?php
for ($i = 1; $i <= 10; print $i."<br>", $i++) ;
?>

ejemplo65.php
for ( desde ; hasta ; incremento ):
.........
...instrucciones....
.........
endfor;

Esta sintaxis es alternativa a la primera de las descritas. Sustituye la { por dos puntos (:) y la } por endfor.

<?php
for($i = 1; $i <=10;$i++) :
echo $i,"<br>";
endfor;
?>

ejemplo66.php
<?php for ($i = 1; $i <= 10;$i++):?>
<H1>Esto se repetirá 10 veces</H1>
<? endfor; ?>

ejemplo67.php

Pág. 115
Como puedes observar en este último ejemplo también es aplicable aquí la sintaxis de los dos sripts PHP. El
primero contiene las instrucciones del bucle y el segundo señala el final del mismo. Entre ambos scripts se escribe el
código 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 página que lo contiene parecerá que nuestro navegador
se ha quedado colgado aunque en realidad estará esperando a que sea atendida la petición.
Si llega a planteársete ese problema, tendrás que recurrir a la socorrida solución de pulsar ALT+CTRL+DEL
para abortar la petición del navegador.

Pág. 116
Bucles foreach

El bucle foreach

El bucle foreach es específico de los array y aplicable a ellos tanto si son escalares como si su tipo es asociativo.
Tiene dos opciones uso. Mediante una de ellas lee únicamente los valores de los elementos del array. La segunda opción
permite leer el índice y el valor de cada elemento.

Lectura de valores

Utilizando la sintaxis:

foreach ( array as $valor ) {


...instrucciones...
}

donde array es el nombre del array (sin incluir índices ni corchetes), as es una palabra obligatoria y $valor el
nombre de una variable (puede ser creada al escribir la instrucción 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 visualización 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
iteración del bucle y que al acabar este sólo contendrá el último de los valores leídos.

<?php
/* definimos un array escalar utilizando la sintaxis
nombre del array=array (valores de los elemento separados por comas)
si los valores son números 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 extraídos
# y escribimos los valores
foreach($a as $pepe) {
echo $pepe,"<br>";
};
# repetimos el mismo proceso, ahora con $b que es un array asociativo
foreach($b as $pepe) {
echo $pepe,"<br>";
};
?>

ejemplo68.php

Lectura de índices y valores

Con una sintaxis como la que sigue se pueden leer no sólo los valores de un array sino también sus índices.

foreach ( array as $indices => $valores ) {


...instrucciones...
}

Pág. 117
donde array es el nombre de la matriz, as es una palabra obligatoria, $indices es el nombre de la variable que
recogerán 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 función 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 $pepa para recoger los valores
# y separaremos ambas variables por => que es el separador obligatorio
# para estos casos

foreach($a as $pepe=>$pepa) {
echo "Indice: ",$pepe," Valor: ",$pepa,"<br>";
};
foreach($b as $pepe=>$pepa) {
echo "Indice: ",$pepe," Valor: ",$pepa,"<br>";
};
?>

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 información del array
unidimensional obtenido como valor en la primera lectura. La sintaxis sería 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 sería necesario proceder del mismo modo, y habría
que utilizar tantos bucles foreachcomo índices contuviera el array.

<?php
# definamos un array bidimensional
$z=array(
0 => array (
Pág. 118
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

Pág. 119
La instrucción continue

La instrucción continue

Si la instrucción break permite interrumpir el desarrollo de un bucle, mediante continue se puede impedir que,
bajo unas condiciones determinadas, se ejecuten algunas o todas las instrucciones de un bucle sin que por ello se
interrumpa la ejecución de las iteraciones siguientes. Esta instrucción es aplicable tanto a bucles for como a los de
tipo while o do while.

Seguramente los ejemplos nos ayudarán a aclarar un poco más la idea. En este primer ejemplo (un bucle for)
tiene como condición(if):$i % 2 == 0 que, como recordarás, significa que el resto de la división de $i entre dos($i % 2) sea
igual (==) a cero.

En este supuesto (condición de múltiplo de dos) se activará la opción continue y por lo tanto en esa iteración no
se ejecuta la instrucción echo y en consecuencia no se imprimirán en pantalla los múltiplos de 2.

<?php
for ($i=0;$i<=10;$i++){

#condición de múltiplo de 2
if ($i % 2 ==0 ) {
continue ;
}

echo "La variable I vale ",$i,"<br>";


}
?>

ejemplo71.php

Este otro ejemplo (caso de bucle while) la condición establecida para que se ejecute continue es que el valor de
la variable no sea múltiplo de tres, en cuyo caso echo sólo imprimirá los múltiplos de 3.

<?php
$i = 0;
while ($i++ < 14) {

#condición de no múltiplo de 3 usando para distinto la sintaxis !=

if ($i % 3 !=0){
continue ;
}

echo "El valor de i es: ",$i,"<br>";


}

?>

ejemplo72.php

En este nuevo ejemplo utilzaremos un bucle do ... while para presentar en pantalla los múltiplos de 11.

<?php
$i = 0;
do {

# condición de no múltiplo de 11. fíjate en la sintaxis alternativa


# observa que aquí distinto lo hemos escrito <>

if ($i % 11 <>0 ){
Pág. 120
continue ;
}

echo "El valor de i es: ",$i,"<br>";

}while ($i++ < 100)


?>

ejemplo73.php

La instrucción continue n

La instrucción continue puede utilizar un parámetro 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 intérprete de
PHP los considera numerados correlativamente–de dentro hacia fuera– a partir de UNO.

Cuando se ejecuta continue n se redirecciona la iteración al bucle cuyo número coincide con el valor de n.
Obviamente, el valor de nno puede ser nunca mayor que el número de bucles anidados en el script.

Analicemos algunos ejemplos. En este caso el bucle for sería el número UNO y el while sería el número DOS.
Cuando se cumpla la condición que activa continue 2 ($i=3) se redirecciona la iteración al paso
siguiente de while (bucle número 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 ejemplo75.php Caso continue 2 - ejemplo74.php

En este otro ejemplo hemos anidado a tres niveles y hemos escrito continue 3, aunque a la hora de ejecutar los
ejemplos podrás 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

Pág. 121
Expresiones regulares

Búsqueda y reemplazamiento de textos

PHP dispone de varias opciones para realizar tareas de búsqueda y reemplazamiento de textos. La más
antigua, POSIX (PortableOperating System Interface uniX), se anuncia como deprecated a partir de PHP 5.3. Por esa
razón centraremos nuestro análisis en la llamadaPCRE (Perl Compatible Regular Expressions) que parece ser la opción
con más futuro.

Una expresión regular o patrón de búsqueda, es una forma de describir un conjunto de cadenas de carácteres sin
enumerar sus elementos. En el caso de las expresiones regulares compatibles con Perl (PCRE) hemos de empezar
diciendo que han tener señalado su comienzo y su final por dos caracteres idénticos llamados delimitadores pudiendo
realizar esa función cualquier carácter no alfanumérico.

Expresiones tales como: #tomate#, *tomate* o /tomate/ serían patrones válidos, delimitados por #, * o /, para la
búsqueda de la palabratomate.

Empezaremos considerando el caso de que una coincidencia requiera encontrar una identidad plena con el patrón.
Más adelante incidiremos sobre el tema de los patrones de búsqueda y el manejo de su amplísimo abanico de opciones.

Aunque lo trataremos con detalle un poco más adelante vamos a empezar a manejar el modificador i. Cuando
este carácter es añadidodetrás del último delimitador modifica el patrón de búsqueda para considerar las
coincidencias sin hacer distinción entre mayúsculas y minúsculas. Si no se incluyera i la búsqueda atendería al criterio
de que mayúscula y minúscula son caracteres diferentes.

El reemplazamiento

Para poder ilustrar de forma gráfica las características de los diferentes patrones de búsqueda empezaremos por
conocer el manejo de la función:

preg_replace ( patron, sustituta, cadena, limite_coincidencias, $contador )

dónde patron es el patrón de búsqueda, sustituta la cadena que va a sustituir las coincidencias, cadena la cadena
en la que pretendemos realizar la búsqueda y sustitución, limite_coincidencias el número máximo de coincidencias a las
que aplicaremos el reemplazamiento y $contador será el nombre de una variable que puede utilizarse como contador del
número de cambios efectuados.

<?php
/* definimos la cadena en la que pretendemos
realizar la búsqueda y sustitución */
$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 patrón de búsqueda ( / ) */
$delimitador="/";
/* establecemos el modificador i para buscar
sin diferencias mayúsculas de minúsculas */
$modificador="i";
/* recogemos en la variable $patron la expresión 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 patrón de búsqueda: <b><i>".$patron."</i></b>";

Pág. 122
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 restricción 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 mayúsculas/minusculas */
$modificador="";
/* actualicemos la variable patrón con el último cambio */
$patron=$delimitador.$buscar.$delimitador.$modificador;
print "<br /><b>Búsqueda sensible a mayúsculas/minúsculas</b><br>";
print "<br />Mediante el patrón de búsqueda: <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 restricción 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 parámetros limite_coincidencias y $contador se reemplazarán todos los valores posibles sin
recoger en ninguna variable el número de cambios. En el caso de que queramos indicar de forma explícita que se efectúen
todos los cambios posibles asignaremos al cuarto parámetro (limite_coincidencias) el valor -1.

El parámetro patron puede ser un array en el que cada elemento será un patrón de búsqueda. 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 serán
reemplazadas por el valor del elemento de sustituta de igual índice tal como puede verse en los ejemplos de la tabla que
incluimos a continuación. Hemos utilizado en todos los casos el modificador i razón por la cual las búsquedas serán
insensibles a mayúsculas y minúsculas.

Código Ver
Función Descripción
fuente ejemplo
Devuelve una cadena sistituyendo, sin límite de coincidencias, el
preg_replace($patron, $sustituto, $original) Ver Probar
contenido del patrón por la cadena de reemplazamiento
Devuelve una cadena sistituyendo el contenido. El cuarto
preg_replace($patron, $sustituto, $original,n) parámetro (n) establece que solo se reemplazarán las n primeras Ver Probar
coincidencias
Devuelve una cadena sistituyendo el contenido. El cuarto
$contador=0;
parámetro (-1) establece que se reemplazarán todas las
preg_replace($patron, $sustituto, $original, -1, Ver Probar
coincidencias. La variable contador, incluida como quinto
$contador)
parámetro recoge el número de ocurrencias
Cuando el patrón es un array (cada elemento ha de incluir los
$patron=array('/xxx/','/yyy/');
delimitadores) se sustituye cada coincidencia con cualquiera de Ver Probar
preg_replace($patron, $sustituto, $original)
los elementos del array por la cadena de reemplazamiento

Pág. 123
$patron=array('/xxx/','/yyy/'); En el caso de un patrón en forma de array el límite de
Ver Probar
preg_replace($patron, $sustituto, $original,n) coincidencias trata individualmente cada elemento del array
$contador=0;
Si se incluye el parámetro contador se cuantificarán todos los
$patron=array('/xxx/','/yyy/'); Ver Probar
cambios realizados.
preg_replace($patron, $sustituto, $original,n,$contador)
$contador=0;
Aquí utilizaremos dos arrays. Uno para establecer los patrones y
$patron=array('/xxx/','/yyy/');
otro para establecer los reemplazamientos asociados con Ver Probar
$sustituto=array('/zzz/','/ppp/');preg_replace($patron,
aquellos
$sustituto, $original)
$contador=0;
Cuando el patron es un array de mayor longitud que el sustituto
$patron=array('/xxx/','/yyy/');
las sustituciones no definidas serán consideradas como cadenas Ver Probar
$sustituto=array('/zzz/','/ppp/');preg_replace($patron,
vacías
$sustituto, $original)
$contador=0;
$patron=array('/xxx/','/yyy/'); Cuando el patron es un array de menor longitud que el sustituto
Ver Probar
$sustituto=array('/zzz/','/ppp/');preg_replace($patron, los elementos sobrantes de este no producirán ningún efecto
$sustituto, $original)

Patrones de búsqueda

La auténtica potencia de las expresiones regulares radica en el enorme abanico de opciones búsqueda 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 carácteres que tienen un significado especial cuando se


incluyen en una expresión regular. A título puramente enumerativo, forman parte de ese conjunto los
siguientes: ., +, *, {, }, [, ], -, \, ^, $, |, (, ) y ?. Veamos sus significados:

Cuando incluimos un punto como metacaracter en un patrón de búsqueda estamos indicado que se admite
cualquier carácter en la posición que ocupa el punto. Es decir, el patrón p. consideraría coincidencia tanto pa, como pz,
como p3.

Cuando un patrón incluye un signo más se está especificando que el carácter que le precede puede
repetirse una o más veces. Es decir pa+ consideraría coincidencias a: pa, paa, paaa y también a paaaaaaa.

Este metacaracter es ligeramente diferente al anterior. También permite repeticiones pero no obliga a que
aparezca el carácter que le precede. Es decir, el patrón pa* consideraría coincidencias a: pa, paa, paaa y
también p3 y pz que no incluyen ninguna a detrás de la p.

{m,n}

Cuando se incluyen esta expresión (en la que m y n son dos números naturales) a continuación de un caracter
cualquiera se especifica que se considerará coincidencia cualquier cadena que contenga ese carácter repetido un
número 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.

Pág. 124
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 se considerará coincidencia cuando el carácter se repita m o más veces.

[]

Mediante los corchetes se pueden incluir rangos de caracteres en el patrón de búsqueda. Si se especifican letras
o números sin ningún separador se considerará coincidencia cualquiera de ellos. Si se separan por medio de un
guión – dos números o dos letras se considerará coincidencia cualquiera del rango delimitado por ellos. Puedes verlo en
los ejemplos.

Cuando este símbolo (acento circunflejo) se incluye como primer carácter dentro de un corchete será interpretado
como negación, es decir, no se considerará coincidencia la expresión que le preceda.

Patrón de
Descripción
búsqueda
Escribe una "o" marcada con colores sustituyendo a cada "o" de la cadena original sin diferenciar mayúsculas de
o minúsculas. Es idéntico al caso del los ejemplos anteriores
Considerará coincidencias todas las d junto su carácter siguiente sea cual fuere (el punto indica que puede ser un carácter
d. cualquiera). Cada coincidencia la reemplazará por do sin diferenciar mayúsculas de minúsculas
Considerará coincidencias todas las "d" seguida de una "o" repetida cero o más veces. Cada coincidencia será
do* reemplazada por "do"

do+ Considerará coincidencia cada "d" seguida de una "o" repetida una o más veces y reemplazará cada coincidencia por "do"

o{3} 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
o{1,} reemplazando cada coincidencia por una "o" coloreada
Considerará coincidencia los grupos "oo", "ooo" "oooo" (entre 2 y 4 repeticiones) y reemplazará por por una "a" cada una
o{2,4} de las coincidencias

[abcd] 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
[^abcd] por un *

[a-h] Considera coincidencia cualquier caracter comprendido entre a y h (ambos inclusive)

[^a-h] Considera coincidencia cualquier caracter no comprendido entre a y h (ambos inclusive)

[0-9] Considera coincidencia cualquier dígito comprendido entre 0 y 9 (ambos inclusive)

[^0-9] Considera coincidencia cualquier dígito no comprendido entre 0 y 9 (ambos inclusive)

Cuando se utilizan expresiones del tipo[0-9], [A-Z] los extremos de los intervalos se delimitan por los valores de los códigos ASCII del primero
y último de los caracteres entendiendo como valores pertenencientes a ese rango aquellos carácteres cuyo código AS CII pertenezca a ese
intervalo. El código 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 atención a los extremos ya que si estableciéramos un rango como [a-Z] estaríamos indicando un intervalo
inaceptable ya que comenzaría en 97 y acabaría en 90 (ha de ser siempre mayor el segundo valor que el primero) y nos daría 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 carácter más en un patrón de búsqueda. Para utilizarlos de esta forma es necesario «escaparlos», es
decir, anteponerles el carácter \. De esa forma serían interpretados como texto.

Además de la utilidad mencionada en los párrafos anteriores, cuando se antepone el carácter de escape a algunos
carácteres (distintos de los metacaracteres) se activan algunas condiciones especiales tal como puedes ver en la tabla
de ejemplos que tienes a la derecha.

La función: $r= preg_quote($c, $d) recoge en la variable $r el resultado de aplicar esa secuencia de escape a la
cadena contenida como parámetro en la variable $c. El parámetro $d deberá recoger el carácter delimitador del patrón
de búsqueda.

En esta tabla recogemos algunos ejemplos del uso de las secuencias de escape en los patrones de búsqueda.

Pág. 125
Patrón de
Descripción
búsqueda

\d Considera coincidencia cualquier caracter que sea un dígito comprendido entre 0 y 9 (ambos inclusive). Equivale a [0-9]

\D Considera coincidencia cualquier caracter que no sea un dígito comprendido entre 0 y 9 (ambos inclusive). Equivale a [^0-9]

\s Considera coincidencia los espacios en blanco

\S Considera coincidencia cualquier caracter que no sea un espacio en blanco


Considera coincidencia cualquier carácter de la "a" a la "z" (excluyendo la ñ y caracteres con tilde) o cualquier número del 0
\w al 9. No incluye los espacios entre las coincidencias
Considera NO COINCIDENCIA cualquier carácter de la "a" a la "z" (excluyendo la ñ y caracteres con tilde) o cualquier
\W número del 0 al 9

\n Considera coincidencia los saltos de línea (no se consideran como tal las etiquetas <br>)

Al anteponerle el \ a un metacaracter es considerado como un carácter normal en la cadena de búsqueda. Si no lo


\/ hiciéramos nos daría un mensaje de error
En este ejemplo puede verse la utilidad de la función preg_quote

Alternacias

La alternancia utiliza el carácter | para permitir una elección entre dos o más alternativas. Cuando se conjugan
incluidas entre paréntesis y teniendo en cuenta que los paréntesis pueden agruparse y/o anidarse pueden construirse
expresiones tan complejas como necesitemos.

Patrón de
Representa a
búsqueda

a|b|c Se considera coincidencia la presencia de uno cualquiera de los caracteres. Todas la coincidencias se reemplazarán por *
Se considera coincidencia la presencia de uno cualquiera de los caracteres del primer paréntesis segudio de uno de los
(a|b)(c|d) caracteres del segundo. Serán coincidencias: ac, ad, bc y bd. Todas la coincidencias se reemplazarán por *

Anclas

En los ejemplos que hemos visto hasta ahora las coincidencias podrían producirse en cualquier parte de la cadena
en la que efectuamos la búsqueda. Estas condiciones pueden modificarse restringiendo la búsqueda al principio o al final
de la cadena de búsqueda. Para el primer caso se antepone al patrón el metacaracter ^.

¡Cuidado!

El metacaracter ^ tiene dos utilidades manifiestamente distintas. Dentro de un corchete [^a] significa
negación («no igual a 'a'» en este caso) y fuera de él y como primer carácter del
patrón ^[abc] o ^pepe hace labores de ancla para restringir la búsqueda 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


metacarácter $ que debe ser incluido detrás del patrón de búsqueda. Tanto este metacarácter como ^ cambian su
funcionalidad cuando se incluye el modificador m. Cuando se da esta situación considerará comienzo y final tanto el
comienzo y el final de la cadena como las posiciones anteriores y posteriores al carácter de salto de línea \n tal como
puedes ver en algunos de los ejemplos de la tabla siguiente.

Patrón de
Representa a
búsqueda

^[abcd] Considera coincidencia sólo si uno de los caracteres incluidos en el corchete aparece al comienzo de la cadena

Pág. 126
Utilizando el modificador A en el patrón (en este caso incluimos los caracteres delimitadores en el patrón) se logra el
/[abcd]/A mismo objetivo que en el ejemplo anterior

[abcd]$ Considera de los caracteres incluidos entre corchetes al final de la cadena

Utilizando el modificador m en el patrón se comprueban las coincidencias de los caracteres situados al comienzo de cada
/^[abcd]/mi línea. Se considera perteneciente a una nueva línea cada el carácter que vaya inmediatamente después de la
secuencia \n
Utilizando el modificador m en el patrón se comprueban las coincidencias de los caracteres situados al final de cada línea.
/[abcd]$/mi Se considera último carácter de una línea 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 número de caracteres posibles. Eso significaría que un patrón de búsqueda
del tipo a.*z considerará como una sola coincidencia la porción 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 patrón de búsqueda agregando el
signo ? inmediatamente después de un indicador de repeticiones (+,* o {m,n}). De esa forma a.*?z consideraría como
coincidencia la porción de texto delimitado por cada "a" de la cadena y la primera de las "z" que aparezcan después de
ella.

La segunda forma de invertir la codicia es agregar el modificador U con lo cual la cadena patrón podría ser similar
a esta: /a.*z/U con los mismos resultados descritos en el párrafo anterior.

ejemplo119.php Ver código fuente

Subpatrones

Cuando una expresión regular se encierra en un paréntesis pasa a constituir un subpatrón de captura que, por
defecto, tiene dos utilidades prácticas. La primera es su condición de ser parte del patrón que la contenga incluidas las
eventuales condiciones de alternancia(a|b) que pueda contener. Junto con esa función los subpatrones disponen de otra
muy importante: la captura. Las coincidencias son almacenadas en memoria con la opción de poder ser utilizadas a través
de lo que se conoce como retro referencias.

Fuera de una clase carácter, una barra invertida seguida por un dígito mayor que 0 es una retro-referencia a
un subpatrón de captura anterior. La retro-referencia no recoge el subpatrón sino el valor de la cadena coincidente con
el subpatrón al que alude. Las retro referencias pueden marcarse así: \\n, \\gn o \\g{n} siendo en los tres casos n el número
de orden del sub-patrón contando de izquierda a derecha.

Veamos su comportamiento con un ejemplo. Si comparamos la cadena "Me gusta el atún rojo con tomate" con el
patrón el ((atún|bonito)(blanco|rojo)) vamos a encontrar una coincidencia del patrón completo (atún rojo), y las
coincidencias de cada uno de los subpatrones: atúnen el caso del primero, y rojo en el caso del segundo. Tales
coincidencias son numeradas para su uso como retro referencias por medio de números naturales 1, 2 y 3 que se
corresponden con los paréntesis contados de izquierda a derecha.

Por ese criterio de asignación la retro referencia \1 (siempre se antepone \ para aludir a ellas) recogerá el valor atún
rojo, \2 contendráatún y \3 incluirá rojo.

Hay situaciones en las que no es necesario usar retro referencias y, dado que pueden ralentizar la operación y
requerir abundante espacio de memoria, puede resulte conveniente desactivarlas.

Para ello basta con que incluyamos después del paréntesis de apertura del patrón (o del subpatrón) los
metacaracteres ?:.

Aquí tienes algunos ejemplos de utilización de retro referencias.

Patrón de búsqueda Representa a


El subpatrón buscará el carácter a o b. El resultado será capturado como \1. Incluyendo la referencia a esa captura
(a|b)\\1 como carácter siguiente serán coincidentes con el patrón las cadenas aa y bb.

Pág. 127
El primer carácter será una letra ó número (\w) que ha de coincidir con el cuarto carácter de la cadena (\\1). El
(\w)(\w)\\2\\1 segundo puede ser también cualquier letra (\w) que ha de coincidir con el tercer carácter de la cadena(\\2)
El primer subpatrón (identificado mediante \1) sería el más exterior de todos (marcado en rojo). Incluye dos
((\w)(\w))\\3\\2\\1 subpatrones que numerados de izquierda a derecha resultarán identificados por \\2 y \\3 (verde y azul
respectivamente)
El primer subpatrón ha de contener una de las cadenas ac, ad, bc, o bd y, además ha de repetirse (\\1) por tanto
((a|b)(c|d))\\1 serán coincidencias: acac, adad, bcbc y bdbd

(?:a|b)\\1 Dará error ya que ?: es el indicador de no captura lo cual hace inválida la referencia \\1

(?:a|b) Eliminando la retroreferencia \\1 del ejemplo anterior funciona correctamente


Funciona exactamente igual que el último ejemplo de la tabla anterior. Las referencias eliminadas no están
((?:a|b)(?:c|d))\\1 incluidas en el patrón de búsqueda 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
función es la de incluiro excluir modificadores a lo largo del patrón de búsqueda. Dada su condición de subpatrones
han de comienzar y terminar por paréntesis (). Por su carácter especial han de llevar ? después del paréntesis de
apertura (?) y a continuación pueden incluir uno o varios modificadores. Si se trata de activarlo basta con poner el carácter
representativo (A, i, m, etcétera) y para desactivarlos se incluye un signo menos (-) delante de ese carácter.

Por ejemplo (?A-im) activaría el modificador A, desactivaría el i y activaría el m siempre a partir de la posición del
patrón de búsqueda en el que es incluido este subpatrón.

Patrón de búsqueda Representa a


El primer subpatrón activa la opción sensible a mayúsculas/minúsculas y la aplica al primer carácter.
(?-i)[A-Z](?i)[a-z]* Para los siguientes caracteres el subpatron (?i) vuelve a desactivar esa opción.

Subpatrones con aserciones

Otra situación especial es el caso de las aserciones. En este caso se contemplan cuatro posibilidades. En
subpatrón y(?=x) donde x ey son condiciones, exige que se cumpla la condición x inmediatamente después de
hacerlo la condición y. Si cambiáramos el signo = por !la expresión y(?!x) será interpretada como exigencia de que NO
se cumpla la condición x después de hacerlo la condición y

Anteponiendo un < al signo = (o a !) podrían plantearse expresiones del tipo (?<=x)y ó (?<!x)y que
serían exigencias del cumplimiento (o no cumplirse si se trata de !) de la condición x inmediatamente antes de
que se cumpla la condición y.

Patrón de búsqueda Representa a


Considera coincidencia cualquier letra ([a-z]) qué esté situada detrás de un número comprendido entre
(?<=[0-9])[a-z] 0 y 9 ([0-9])
Considera coincidencias cualquier letra ([a-z]) qué NO ESTÉ situada detrás de un número comprendido
(?<![0-9])[a-z] entre 0 y 9 ([0-9])

[0-9](?=[A-Z]) Considera coincidencia cualquier número ([0-9]) qué vaya delante (lleve detrás) de una letra ([A-Z])
Considera coincidencia cualquier número ([0-9]) qué NO VAYA delante (NO lleve detrás) una letra ([A-
[0-9](?![A-Z]) Z])

Subpatrones condicionales

También 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 condición x será usado el patrón de búsqueda(o subpatrón) x. En caso de que no se cumpla la condición
se utilizaría, en caso de haber sido especificado, el patrón z.

Pág. 128
Las condiciones sólo 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 bastaría incluir dentro del paréntesis
que contiene la condición x el número de la retro referencia (n) sin anteponerle ningún otro carácter. Puedes verlo en los
ejemplos de la tabla.

En la tabla que tienes a continuación hemos incluido una serie de ejemplos que contemplan algunas de las
múltiples posibilidades que ofrecen los subpatrones condicionales. Es particularmente importante prestar mucha atención
a la elaboración 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.

Patrones de búsqueda Representan a

([0-9]*)(?(1)[a-c]|[d-z])
Todos estos ejemplos tienen marcado en rojo el condicional, dentro de él van la retro referencia, el
(\"|\')(\<.*?)*(?(2)\\1|.*?\\1) patrón que usará si se cumple la condición y el patrón que usará si no se cumple la condición.
((a)|(b))(?(3) f| c)
([0-9]*)(?(1)[a-c])
Los ejemplos anteriores sin incluir patrón para el caso en que no se cumple la condición.
(\"|\')(\<.*?)*(?(2)\\1)
En los ejemplos se comenta lo relativo a los caracteres prec edidos del símbolo \.
((a)|(b))(?(3) f)
([0-9]*)(?(1)|[d-z])
(\"|\')(\<.*?)*(?(2)|.*?\\1) Ahora hemos quitado a los ejemplos iniciales el patrón para el caso de que se cumpla la condición.

((a)|(b))(?(3)| c)
([0-9]*)(?(1))
(\"|\')(\<.*?)*(?(2)) Aquí hemos eliminado del condicional ambos patrones.

((a)|(b))(?(3))
Patrón de búsqueda Representa a
Si se cumple la condición verde(un número delante de una letra) agrupa esa condición a la H para
(?(?<=[0-9][a-z])H|más) conformar la palabra a buscar. Si no se cumple aquella condición considera patrón de búsqueda la
palabra "más"
Si se cumple la condición verde(un número delante de una letra) agrupa esa condición a la H para
(?(?<![0-9][a-z])H|más) conformar la palabra a buscar. Si no se cumple aquella condición considera patrón de búsqueda la
palabra "más"
Si se cumple la condición verde(un número delante de una letra) agrupa esa condición a la H para
H(?(?=[0-9][a-z])|más) conformar la palabra a buscar. Si no se cumple aquella condición considera patrón de búsqueda la
palabra "más"

Utilizando las opciones que nos ofrecen cada uno de los elementos que hemos ido viendo a lo largo de esta página
podremos componer patrones de búsqueda 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 página siguiente, los usos que podemos dar a los patrones en PHP.

Otras funciones con expresiones regulares

La función preg_match

Cuando se trata únicamente de conocer la existencia o inexistencia de texto dentro de una cadena o de un fichero
puede resultar útil la función:

preg_match( patron, cadena, $coincidencias )

realiza una búsqueda en la cadena por medio de la expresión regular incluida en el patron. Si encuentra alguna
coincidencia devuelve el valor booleano TRUE, en caso contrario devuelve FALSE.

El parámetro $coincidencias es opcional. Cuando se incluye recogerá en un array con ese nombre los resultados
de la búsqueda.

Pág. 129
Información sobre variables

Obtener información sobre variables

Veremos aquí algunas de las múltiples funciones que nos permiten obtener información sobre arrays y variables.

sizeof(variable)

La función sizeof devuelve el número de elementos de un array. Si se aplica sobre una variable (no array)
devolverá uno y tanto si se aplica sobre un array vacío, una variable con valor nulo o sobre una variable no definida,
devolverá cero.

count(variable)

Tiene idéntica funcionalidad a la de sizeof.

<?php
$a=array("Lunes","Martes","Miercoloes","Jueves",
"Viernes","Sábado","Domingo");
$b=array(
"Precio" => "17340 euros",
"Color" => "Rojo",
"Llantas" => "Aluminio");
$c=47; $d=""; $e=array();

echo "<h3>Valores usando sizeof()</h3>";

@print " a tiene: ".sizeof($a)." elementos<br>";


@print " b tiene: ".sizeof($b)." elementos<br>";
@print " c tiene: ".sizeof($c)." elementos<br>";
@print " d tiene: ".sizeof($d)." elementos<br>";
@print " e tiene: ".sizeof($e)." elementos<br>";
@print " f tiene: ".sizeof($f)." 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 función isset comprueba si una variable está definida. Si está definida –incluso con valor nulo o como array
vacío– isset devolveráUNO, en caso contrario devolverá NUL. Esta función puede ser un complemento de sizeof o
de count dado que permitiría comprobar si están definidas las variables en las que aquellas funciones devuelven
dimensión cero.

empty(variable)

La función empty comprueba si una variable está vacía o no está definida. Si está vacía (valor nulo o array
vacío) o no está definidaempty devolverá UNO, en caso contrario devolverá NUL.

Pág. 130
¡Cuidado!

No confundas isset con empty. No devuelven los mismos resultados. Mientras que isset sólo comprueba si
una variable está definida (tiene un valor aunque sea nulo) la función empty comprueba que la
variable no esté definiday, 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 idénticas– 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 –también idénticas– 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 después de aplicar unset sobre una variable aplicamos de nuevo la función isset,
nos devolverá NUL indicando que ya no está definida. La función unset se puede aplicar tanto sobre variables como
sobre un array y también sobre un elemento de un array.

<?php
$a=array("Lunes","Martes","Miercoloes","Jueves",
"Viernes","Sábado","Domingo");
$b=array(
"Precio"=>"17340 euros",
"Color" =>"Rojo",
"Llantas" =>"Aluminio");
$c=47; $d=""; $e=array();

echo "<h3>Variables definidas</h3>";

echo " ¿Esta definida la variable a ? ",isset($a),"<br>";


echo " ¿Esta definida la variable b ? ",isset($b),"<br>";
echo " ¿Esta definida la variable c ? ",isset($c),"<br>";
echo " ¿Esta definida la variable d ? ",isset($d),"<br>";
echo " ¿Esta definida la variable e ? ",isset($e),"<br>";
echo " ¿Esta definida la variable f ? ",isset($f),"<br>";

echo "<h3>Identificación de tipos de variables</h3>";

Pág. 131
echo " ¿La variable a es un array ? ",is_array($a),"<br>";
echo " ¿La variable a es tipo double ? ",is_double($a),"<br>";
echo " ¿La variable a es un entero ? ",is_int($a),"<br>";
echo " ¿La variable a es un entero ? ",is_long($a),"<br>";

echo "<h3>Eliminando variables</h3>";

echo "La dimensión de a es: ",count($a),"<br>";


unset($a[0]);
echo "Nueva dimensión de a: ",count($a),"<br>";
echo "La dimensión de b es: ",count($b),"<br>";
unset($b);
@print "Nueva dimensión 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

Pág. 132
Recuentos en arrays

Recuento de los valores contenidos en una matriz

Algunas de las posibilidades de obtener información sobre los contenidos de un array son las siguientes:

$recuento=array_count_values(array)

Con array_count_values la variable $recuento será un nuevo array cuyos índices son cada uno de los valores
distintos que contengaarray y cuyos valores serán el resultado de contar el número de veces que se repite este nuevo
índice en el array inicial. Distingue entremayúsculas y minúsculas. Cuando los valores del array inicial (array) son números
enteros (sea array escalar o asociativo) $recuento será unarray escalar. En caso contrario, será asociativo.

Búsqueda de elementos en un array

claves=array_keys(array)

Devuelve un array escalar (claves) que contiene como valores los índices del array inicial (array).

claves=array_keys(array, valor)

Devuelve un array escalar (claves) que contiene como valores los índices de los elementos del array inicial cuyo
valor coincide con el indicado mediante el parámetro valor.

valores=array_values(array)

Esta función recoge en una nueva matriz (valores) todos los valores contenidos en el array. Es una forma de
conversión 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>";
Pág. 133
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

Pág. 134
Ordenación de arrays (I)

Localización de valores en una matriz

in_array(valor,array)

La función in_array busca en la matriz (array) el valor (numérico o cadena) contenido en el parámetro valor. Si lo
encuentra devuelve 1, y si no existiera devolvería NUL.

Posicionamientos en una matriz

Mediante estas funciones se puede modificar la posición del puntero interno de una matriz y determinar
los índices de los elementos a los que apunta en cada momento.

key(array)

Devuelve el índice del elemento de la matriz al que apunta en ese momento el puntero interno de la matriz.

reset(array)

Desplaza el puntero interno a la posición del primer índice del array.

end(array)

Desplaza el puntero interno a la posición del último índice del array.

pos(array)

Mantiene el puntero interno en la posición del actual.

next(array)

Avanza el puntero interno en una posición respecto a la actual.

prev(array)

Retrocede el puntero interno en una posición respecto a la actual.

Moviendo el puntero interno

<?php
$a=array(1,2,3,1,1,2,3,3,4,4,4,0,1);
$b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul");
$c=array(
"a"=>"rojo",
"b" =>"verde",
"c" =>"rojo",
"d" =>"rojo",
"e" =>"verde",

Pág. 135
"f" =>"Rojo",
"g" =>"Verde");

echo "<h3>Busca un valor en una matriz</h3>";

echo " Busca el valor en la matriz: <b>#",in_array(3,$a),


"#</b> Si no ha puesto nada no estaba, si 1 lo encontró <BR>";
echo " Busca el valor en la matriz: <b>#",in_array(7,$a),
"#</b> Si no ha puesto nada no estaba, si 1 lo encontró <BR>";
echo " Busca el valor en la matriz: <b>#",in_array("gris",$b),
"#</b> Si no ha puesto nada no estaba, si 1 lo encontró <BR>";
echo " Busca el valor en la matriz: <b>#",in_array("blanco",$b),
"#</b> Si no ha puesto nada no estaba, si 1 lo encontró <BR><br>";

echo "<h3>Posicionandose y determinando indices actuales</h3>";

echo "Este el valor asoaciado al indice 3 de la matriz a: ",$a[3],"<br>";


echo "El puntero interno apunta a la clave: ",key($a),"<br>";
echo "Este es el valor siguiente al anterior: ",next($a),"<br>";
echo "El puntero interno apunta a la clave: ",key($a),"<br>";
echo "Este es el primer valor de la matriz a: ",reset($a),"<br>";
echo "El puntero interno apunta a la clave: ",key($a),"<br>";
echo "Este es el ultimo valor de la matriz a: ",end($a),"<br>";
echo "El puntero interno apunta a la clave: ",key($a),"<br>";
echo "Este es el penúltimo valor de la matriz a: ",prev($a),"<br>";
echo "El puntero interno apunta a la clave: ",key($a),"<br>";
echo "Este es el mismo valor anterior: ",pos($a),"<br>";
echo "El puntero interno apunta a la clave: ",key($a),"<br>";

echo "Este el valor asoaciado al indice 4 de la matriz b: ",$b[4],"<br>";


echo "El puntero interno apunta a la clave: ",key($b),"<br>";
echo "Este es el valor siguiente al anterior: ",next($b),"<br>";
echo "El puntero interno apunta a la clave: ",key($b),"<br>";
echo "Este es el primer valor de la matriz a: ",reset($b),"<br>";
echo "El puntero interno apunta a la clave: ",key($b),"<br>";
echo "Este es el ultimo valor de la matriz a: ",end($b),"<br>";
echo "El puntero interno apunta a la clave: ",key($b),"<br>";
echo "Este es el penúltimo valor de la matriz a: ",prev($b),"<br>";
echo "El puntero interno apunta a la clave: ",key($b),"<br>";
echo "Este es el mismo valor anterior: ",pos($b),"<br>";
echo "El puntero interno apunta a la clave: ",key($b),"<br>";

?>

ejemplo152.php

Pág. 136
Ordenación de arrays (II)

Ordenaciones de arrays

Los elementos de un array se van ordenando según se van definiendo. Por tanto, su orden no es el mismo que el
de los valores de sus índices. Las funciones PHP que ordenan los elementos de un array permiten dos opciones. Con
una de ellas es posible la ordenación de los elementos sin modificar los valores de los índices, mientras que la otra sí
modifica los índices. En el segundo de los casos la modificación puede afectar incluso al tipo de índices dado que los
resultados de las ordenaciones –tanto si hemos partido de un array escalar como si lo hemos hecho desde
uno asociativo– es siempre un array escalar.

Ordenación por valores sin mantener índices

sort(array)

Ordena los valores del array en sentido creciente y lo reindexa asignando índice CERO al menor de los valores.

rsort(array)

Ordena la matriz en sentido decreciente de sus valores y la reindexa asignando índice CERO al mayor de estos.

Ordenación por índices

ksort(array)

Ordena la matriz según sus índices y en sentido creciente de estos.

krsort(array)

Ordena la matriz por índices en sentido decreciente de los mismos.

Ordenación por valores manteniendo índices

asort(array)

Ordena la matriz según 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.

Ordenación mediante función definida por usuario

PHP permite que el usuario pueda definir funciones en las que establezca sus criterios particulares de ordenación.
Las funciones PHP que permiten usar esta característica son las siguientes:

uasort(array, funcion)

Ordena la matriz utilizando los criterios establecidos por la función definida por el usuario y mantiene los índices
del array.

Pág. 137
usort(array, funcion)

Ordena la matriz por valores utilizando los criterios definidos en la función de usuario y modifica los índices.

uksort(array, funcion)

Ordena la matriz por claves utilizando los criterios definidos en la función.

En el ejemplo hemos definido una función de comparación siguiendo el criterio de ser o no ser múltiplo de 2.
Trataremos las funcionesen 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 número negativo como respuesta y en caso contrario uno positivo. De esta forma
los valores del array que devuelven negativos se consideran anteriores en la ordenación a los que dan como resultado un
número positivo.

<?php
$a=array(1,2,3,1,1,2,3,3,4,4,4,0,1);
$b=array("blanco","azul","blanco","blanco","azul","Blanco","Azul");
$c=array(
"b" =>"verde",
"c" =>"rojo",
"e" =>"verde",
"f" =>"Rojo",
"g" =>"Verde",
"a"=>"rojo",
"d" =>"rojo",);

sort ($a);

echo "<h3>Ordenación por valores usando sort</h3>";


foreach ($a as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";
}

sort ($c);

echo "<h3>Ordenación por valores usando sort</h3>";


foreach ($c as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";
}

rsort($a);

echo "<h3>Ordenación inversa por valores usando rsort</h3>";


foreach ($a as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";
}

ksort($b);

echo "<h3>Ordenación por claves usando ksort</h3>";


foreach ($b as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";

krsort($b);

echo "<h3>Ordenación inversa por claves usando krsort</h3>";


foreach ($b as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";
Pág. 138
}

asort($c);

echo "<h3>Ordenación por valores manteniendo indices </h3>";


foreach ($c as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";

arsort($c);

echo "<h3>Ordenación inversa por valores manteniendo indices arsort</h3>";


foreach ($c as $clave=>$valor){
echo "Clave: ",$clave," Valor: ",$valor, "<br>";

}
echo "<h3>Ordenación por valores mediante
función de usuario manteniendo indices</h3>";

/* esta función recoge el valor de la variable $a


y aplicar el operador de comparación 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
comparación de modo que los valores -2 serán 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>Ordenación por clave mediante función de usuario </h3>";

uksort ($a, 'micomparar');

foreach ($a as $clave=>$valor){


echo "Clave: ",$clave," Valor: ",$valor, "<br>";

echo "<h3>Ordenación por valores mediante función de usuario </h3>";

usort ($a, 'micomparar');

foreach ($a as $clave=>$valor){


echo "Clave: ",$clave," Valor: ",$valor, "<br>";

?>

ejemplo153.php

Pág. 139
Modificación de arrays

Modificaciones en arrays

var= range(inferior, superior)

Crea una nueva matriz escalar (var) en la que los valores de los elementos serán los números enteros
(ordenados) pertenecientes al intervalo comprendido entre los valores inferior y superior, incluidos estos.
Tanto inferior como superior deben ser números enteros.

shuffle(array)

Intercambia de modo aleatorio los valores de un array y los reindexa. Igual que ocurría en el caso de los números
aleatorios, la funciónshuffle deberá ir precedida de una semilla del tipo srand. En el ejemplo hemos usado
como semilla la función: 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 estén los índices, esta función, en
caso de valores repetidos, toma cada uno de esos valores una sola vez, lo utiliza como índice del nuevo array y asigna
como valor del nuevo elemento el mayor de los índices –del array original– de los elementos que contuvieran ese valor.

Insertando elementos en un arrays

array_unshift(arr, v1,v2,..)

Inserta al principio de la matriz arr los valores v1, v2, etcétera 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, etcétera, 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 numéricos.

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 insertaría al comienzo del mismo. A los nuevos elementos del array se les asignan
índices numéricos.

array_merge($a, $b)

Crea un nuevo array escalar en el que se incluyen todos los elementos contenidos en los arrays $a y $b.

Quitar elementos de un array

Pág. 140
array_shift($a)

La función array_shift extrae el primer elemento del array $a.

array_pop($a)

La función array_pop extrae el último elemento del array $a.

array_slice($a,n)

La función 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 posición n contando desde el primero hasta el último según el orden de creación de los elementos.
Si el valor de n es negativo extraerá todos los elementos a partir del enésimo, esta vez contando desde el último hasta
el primero.

array_slice($a,n, m)

La función array_slice con dos parámetros 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 posición enésima de primero a último.
 – Cuando n es negativo y m es positivo se extraerán m elementos contados a partir del enésimo, esta vez recorriendo
el array deúltimo a primero.
 – En el caso en que n tenga valor positivo y m sea negativo extraerá los comprendidos entre el enésimo contado
de primero a últimoy el emésimo contado desde el último hasta el primero.
 – Si n es negativo y m es también negativo extraerá los caracteres comprendidos entre el enésimo contado de último a
primero y elemésimo 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 condición devolverá un array vacío.

Invertir el orden de un array

array_reverse(array)

Devuelve un nuevo array cuyos elementos están en orden inverso al del array original. De esta forma el elemento
que ocupaba la última posición pasa a ocupar la primera y así sucesivamente.

¡Cuidado!

Recuerda que las posiciones iniciales de los elementos de un array no tienen relación con sus índices sino
con la secuencia en la que fueron creados.

Y otra cosa, mucho cuidado con la aplicación de todas estas funciones y con los índices de los arrays
resultantes.

Fíjate en los ejemplos y verás que algunas estas funciones reindexan los resultados y los convierten en
escalares aún 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",

Pág. 141
"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 números 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>";


Pág. 142
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);

Pág. 143
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

Pág. 144
Funciones de usuario

¿Qué son las funciones de usuario?

De igual forma que lo hace el navegador en el caso del HTML, PHP lee e interpreta las instrucciones contenidas
en los scripts de formasecuencial. Es decir, las instrucciones se van ejecutando en el mismo orden en el que aparecen
en el documento original, con la excepción de las funciones ya que estas son bloques de instrucciones son puestos a
disposición de PHP que no se ejecutarán hasta el momento en que sean requeridas de forma expresa.

¿Dónde deben insertarse?

Aunque en versiones antiguas de PHP era necesario definir la función antes de invocarla, a partir de la versión
4 no es necesaria esa organización secuencial. La función pueden estar escrita dentro de cualquier script y en cualquier
parte del documento, sin que tenga importancia alguna el lugar en el que se incluya la llamada a la misma.

También es posible –y bastante habitual– incluir funciones de uso frecuente en documentos externos de modo
que pueden sercompartidas. En este caso, además de invocarla es necesario indicar a PHP el lugar donde debe buscarla.
Hablaremos de ello cuando estudiemos lo relativo a include.

Definición de la función

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 minúsculas.


 El nombre de la función, que debe seguir criterios similares a los de los nombres de variables, aunque en este
caso no se antepone el símbolo $ ni ningún otro.
 Los paréntesis (), incluso cuando no contengan nada.
 Las llaves de apertura ({) y cierre (}) entre las que se escribirán las instrucciones correspondientes a la función.

Ejecución de la función

Las funciones PHP no se ejecutan en tanto no sean invocadas. Para invocar una función la sintaxis es la
siguiente:

nombre()

Al ser llamada con esta sintaxis –desde cualquier script– se ejecutarán las instrucciones contenidas en ella.

Con este primer ejemplo obtendremos una página en blanco. El script contiene una función pero no hay ninguna
instrucción que la invoque y por lo tanto no se ejecutaría.

<?php
function a1(){

for($i=1;$i<=10;$i++){
echo $i,"<br>";
}
}

Pág. 145
?>

ejemplo155.php

<?php
a1();
?>
<!-- Hemos escrito un script con una llamada
a la función a1 que aún no está definida.
Tendremos que hacerlo, pero no importa
la parte del documento en la que lo hagamos
La pondremos en este nuevo script PHP //-->

<?php
function a1(){
for($i=1;$i<=10;$i++){
echo $i,"<br>";
}
}
?>

ejemplo156.php

Ámbito de las variables

Resumamos lo ya comentado cuando tratamos el tema de las variables.

 Las funciones no leen valores de variables definidas fuera de su ámbito salvo que dentro de la propia función se
definan de forma expresa como globales.
 Si una función modifica el valor de una variable global, el nuevo valor persiste después de abandonar la función.
 Si dentro de una función se utiliza un nombre de variable idéntico 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 ejecución.
<?php
# definamos dos variables y asignémosles un valor
$a=5; $b=47;
# escribamos una función a1 y pidámosle que imprima sus valores

function a1(){
@print "Este es el valor de $a en la función a1: ".$a."<br>";
@print "Este es el valor de $b en la función a1: ".$b."<br>";
}
# hagamos una llamada a la función anterior
# no nos escribirá ningún valor porque esas variables no pertenecen
# al ámbito de la función y serán consideradas como vacías
# en el ámbito de la función
a1();
# escribamos una nueva función, definamos como global $a
# y comprobemos que ahora si la hemos incluido en el ámbito
# de la función
function a2(){
global $a;
@print "Este es el valor de $a en la función a2: ".$a."<br>";
@print "Este es el valor de $b en la función a2: ".$b."<br>";
}
# invoquemos esta nueva función y veamos que ahora
# si se visualiza el valor de $a pero no el de $b
a2();
Pág. 146
# creemos una nueva función 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 función a3: ",$a,"<br>";
echo "Este es el valor de $b en la función a3: ",$b,"<br>";
}
# invoquemos la función a3
a3();
# comprobemos -desde fuera del ámbito de la función
# 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 están: ".$_SERVER['SERVER_NAME']."<br>";
}
# invoquemos esta nueva función
a4();
?>

ejemplo157.php

Asignación de valores a variables

A las variables no globales se les pueden asignar sus valores iniciales de dos formas:

 • Incluyéndolas en una línea de instrucciones contenida en la propia función.


 • Insertando los nombres de variable y sus valores dentro del paréntesis que –de forma obligatoria– debe seguir al nombre
de la función.

En este último caso la sintaxis sería:

function nombre_funcion ($variable1=valor1,$variable2=valor2)

donde $variable1 y $variable2 son nombres de variables a utilizar en el ámbito de la función y valor1 y valor2 los
valores asignados a cada una de ellas. En este paréntesis pueden incluirse –separándolas con comas– cuantas
parejas variable = valor sean necesarias.

Una forma alternativa a la anterior sería la siguiente:

function nombre_funcion ($variable1,$variable2)

que requeriría asignar los valores de cada una de la variables desde la llamada a la función, que ahora deberá
tener esta sintaxis:

nombre (valor1, valor2,...);

y donde habría que escribir los valores separados por comas, y encerrados entre comillas cuando se trata de
variables alfanuméricas.

Pág. 147
Si el número de valores contenidos en la llamada fuera mayor que el número de variables definidas en la función,
los excedentes serían ignorados y, si fuera inferior, se asignaría valor nulo a las variables a las que no se transfiriera
ningún valor.

También es posible incluir en la llamada a la función los nombres de algunas variables definidas en el ámbito
externo a la función. Se haría 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 función
function a1($a=56, $b=25){
echo "El valor de $$a en la función a1: ", $a,"<br>";
echo "El valor de $$b en la función a1: ", $b,"<br>";
}
a1();
echo "El valor de $a despues de ejecutar la función es: ",$a,"<br><br>";

# Pasando valores desde la llamada a la función #


/* Definamos una función fun1 e incluyamos dentro de su paréntesis
nombres de variables, separados por comas pero ahora sin asignarles
ningún valor */
function fun1($x,$y,$z){
print "Valor de la variable x: ".$x."<br>";
print "Valor de la variable y: ".$y."<br>";
print "Valor de la variable z: ".$z."<br>";
}

# debemos hacer la llamada a la función pero ahora


# lo haremos de forma distinta.
# Vamos a incluir en la llamada
# los valores que queremos asignar a las variables de la función
# Escribiremos dentro del paréntesis de la llamada
# los valores de cada una de las tres variables
# separados por comas
# (si se trata de una cadena, pongámosla entre comillas)
# y veremos con la función recoge esos valores asignados
#en la llamada

fun1(14,"Robustiano",23.4);
/* si esta llamada contuviera más de tres valores
los últimos serian ignorados */
fun1(49.3,"Eustaquio",78,"Lupicio",456);
# si contuviera menos de tres valores
# PHP nos daría un mensaje de error
# advirtiendo que falta un valor
# pero nos devolvería los valores
fun1("Desiderio","Bailador");

# esos mensajes de error podríamos evitarlos


# poniendo una arroba delante de la llamada a la función
@fun1("Nuevo Desiderio","Nuevo Bailador");

# también podría utilizarse una sintaxis como esta


# en la que dejamos en blanco (entre comillas)

Pág. 148
# el espacio correspondiente al segundo valor
# aunque si incluimos las comas.
# La variable que ocupa esa posición
# sería considerada como nula
fun1("La luna",'',"verde");

# también podríamos incluir en la llamada nombres de variables


# definidas en el ámbito general del sript
# un este caso la función usaria esos valores

fun1($a,$b,$c);

?>

ejemplo158.php

Pasar por referencia

Tal como hemos visto, las funciones PHP pueden recibir valores de variables externas y utilizar esos valores sin
que el valor original de las mismas –salvo que se les asigne la condición de globales dentro de la función– sufra
modificación.

Una manera de lograr que los valores de una variable externa puedan ser modificados por una función, es lo que
se llama en argot informático «pasar variables por referencia».

La forma de hacerlo es esta:

 – Hay que anteponer al nombre de la variable el símbolo & y PHP interpretará que la estamos pasando por referencia.
 – El & puede anteponerse tanto en la definición de la función como en la llamada a la función, tal como puedes ver en el
ejemplo.

La segunda de las opciones nos concede mayor libertad dado que permite usar una sola función y decidir en cada
llamada la forma de pasar los parámetros.

<?php $a=3; $b=2;


function a1($a,$b){
$a=pow($a,2);
$b=pow($b,3);
echo "El cuadrado de a dentro de la función es: ",$a, "<br>";
echo "El cubo de b dentro de la función es: ",$b, "<br><br>";
}

a1($a,$b);

echo "Al salir de la función a conserva la modificación: ",$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 función es: ",$a, "<br>";
echo "El cubo de b dentro de la función es: ",$b, "<br><br>";
}

b1(&$c,$d);

echo "Al salir de la función c conserva la modificación: ",$c, "<br>";


echo "Por el contrario, d no la conserva: ",$d, "<br><br>";
?>

Pág. 149
ejemplo159.php
¡Cuidado!

Si tratas de ejecutar una función en la que colocas el & en la llamada a la función 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 también con la configuración por defecto de algunas versiones de
PHP. A partir de la versión 5.3.3 este mensaje sustituye Warning por Deprecated con lo cual nos advierte
de que se trata de un función que se queda obsoleta y que, probablemente, será desactivida en versiones
posteriores de PHP.
La manera de evitar esa advertencia es no incluir en símbolo & en la llamada a la función.

Otra forma de definir funciones de usuario

Existe otra opción de definición de funciones de usuario que puede resultar de mucho interés. En este caso
la función se define en tres bloques:

 Definición de la función, llave de apertura { y cierre del script PHP (?>).


 Contenido de la función formado exclusivamente por código HTML que será incluido en el documento cuando sea
invocada la función que lo contiene.
 Cierre de la función (llave de cierre }) contenido en un script PHP, es decir, entre las etiquetas de apertura (<?php)
y cierre (?>) de un script de PHP.

Cuando es invocada una función definida de esta forma –puedes verlo en el ejemplo– PHP se limita a escribir en
el documento final los textos contenidos entre la etiqueta de apertura y cierre de la función.

Las funciones de esta forma son particularmente útiles para la construcción de espacios web que contienen una
serie de páginas en las que se repiten las mismas estructuras.

<?php function Encabezado() { ?>


<!-- Hemos abierto la función y cerrado la etiqueta PHP
todo esto es código HTML //-->
<html>
<head>
<title>Titulo de mi página</title></head>
<body bgcolor="#FF0000">
<!-- Esta nueva llamada a PHP
insertando la llave de cierre de la función
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 página web. Llamamos a la función Encabezado
luego escribimos un texto y por último insertamos

Pág. 150
el Pie de página con la función Pie //-->
<?php Encabezado(); ?>
Este es texto que aparecerá en el cuerpo de la página.
Está fuera de los scripts de php y será considerado
como un texto HTML. Debajo aparecerá la línea horizontal
que insertaremos mediante una nueva llamada a la función Pie

<?php Pie(); ?>

ejemplo160.php

Pág. 151
Funciones que devuelven valores

Funciones que devuelven valores

Las funciones PHP pueden ser llamadas a partir de un script y posteriormente recoger –en ese mismo script– los
resultados de su ejecución. Para conseguir este resultado debemos escribir dentro de la función la
instrucción return seguida de la variable o la instrucción cuyo resultado queremos que sea devuelto al script desde el que
ha sido llamada la función.

Tal como podemos ver en el ejemplo, los valores devueltos por return pueden ser presentados directamente en
la página o recogidos por una variable.

También es posible que la función genere un array y que este sea devuelto a una variable que se convertiría a
ese tipo de forma automática.

Otra opción de recoger los valores devueltos por return es invocar la función mediante una llamada del tipo:

list(v1, v2,..)=llamada

Las variables v1, v2, etc. recogerán los valores de los elementos del array devuelto por la función.

<?php
# asignamos valores a dos variables
$a=3; $b=5;
# escribimos una función que eleva la variable a
# a la potencia indicada en b
# insertando return delante de la operación
function a1($a,$b){
return pow($a,$b);
}
#incluimos en la instrucción echo una llamada
# a la función y en ella pasamos los valores
# recogidos en las variables a y b
# return conseguirá que se ejecute esa función
# y que echo recoja e imprima el resultado
echo "El valor de a elevado a b es: ",a1($a,$b),"<br>";
# esta otra función 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 función
$p=a2($a,$b);
# leemos el array devuelto desde fuera de la función
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 función
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

Pág. 152
Funciones de fecha

Funciones de fecha

PHP es pródigo en cuanto a posibilidades de manejo de fechas y horas. Para ello, cuenta, entre otras, con las
siguientes funciones:

date (cadena de formato)

Devuelve valores de fecha y hora actuales utilizando los parámetros que se señalan en la tabla para establecer
el formato de salida de los datos. Dentro de la misma cadena de formato puede contener tantos parámetros como se
deseen.

Parámetros de formato de date()


Valor Funcionalidad Sintaxis Resultado
A AM-PM date("A") AM

a am-pm date("a") am

d Día del mes en formato de 2 dígitos date("d") 03

j día del mes sin ceros a la izquierda date("j") 3

F Nombre del mes (texto completo) date("F") October

M Nombre del mes (3 letras) date("M") Oct

m Nº del mes (de 01 a 12) con dos dígitos date("m") 10

n Nº del mes (de 1 a 12) sin dos dígitos date("n") 10

Y Año con cuatro dígitos date("Y") 2015

y Año con dos dígitos date("y") 15

G Hora 0-23 sin ceros a la izquierda date("G") 5

H Hora 0-23 con dos dígitos date("H") 05

g Hora 1-12 sin ceros a la izquierda date("g") 5

h Hora 01-12 con dos dígitos date("h") 05

i Minutos de 00 a 59 con dos dígitos date("i") 56

s Segundos de 00 a 59 con dos dígitos date("s") 26

l día semana en texto completo date("l") Saturday

D Día de la semana (tres letras) date("D") Sat

w día semana de 0 (domingo) a 6 (sabado) date("w") 6

z días transcurridos del año actual date("z") 275

t Número de días mes actual date("t") 31

L Año actual bisiesto (1), no bisiesto (0) date("L") 0

Z Diferencia (seg.) horaria local con GMT date("Z") 7200

U Segundos Unix Epoch date("U") 1443844586

S Sufijo ordinal inglés date("S") rd

Como puedes ver en este ejemplo, respeta los caracteres separadores (espacios, dos puntos, guiones, etcétera)
que se hubieran incluido en la cadena de formato siempre que no coincidan con ninguno de los parámetros PHP para
esta cadena.

<?php echo "Son las ", date("h : i : s")," y hoy es ", date("j-n-Y")?> devolvería: Son las 05 : 56 : 26 y hoy es 3-10-2015

¡Cuidado!

Pág. 153
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 coincidirán la hora del sistema con la del servidor.

Pero si alojaras esta página en un hosting australiano, PHP nos devolvería los valores con hora y fecha de
lasantípodas.

date (formato, número)

Esta función nos devuelve la fecha y hora del tiempo Unix indicado en el parámetro número. Recuerda que ese
número indicasegundos contados a partir de la 0:00:00 (GMT) del día 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) ?> devolvería: Fué a las 05 : 03 : 46
del 14-6-1984

gmdate(cadena formato)

Se comporta de forma idéntica 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 según accedas a esta página 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 03 : 56 : 26 y hoy es 3-10-
2015

gmdate (formato, número)

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) ?> devolvería: Fué a las 03 : 03
: 46 del 20-6-1984

checkdate(mes,día,año)

Comprueba si los valores de los parámetros mes están dentro del rango permitido (de 1 a 12), si el
parámetro día es un valor válido para ese mes (considera años bisiestos) y si el valor del año 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 Día Año Sintaxis Devuelve
10 32 1987 Checkdate(10,32,1987)
10 31 1987 Checkdate(10,31,1987) 1

2 29 2000 Checkdate(2,29,2000) 1

2 29 2001 Checkdate(2,29,2001)

gettimeofday()

Esta función devuelve un array asociativo con los siguientes índices:


Pág. 154
 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 fracción en microsegundos de hora actual (Unix Each)
 minuteswest
Devuelve los minutos al Oeste de Greenwich
 dsttime
Devuelve el tipo de corrección horaria según 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 Devuelve
$z= gettimeofday();
Array
echo $z;
echo $z['sec']; 1443844586
echo $z[usec]; 21028
echo $z['minuteswest'']; -120
echo $z['dsttime']; 1

getdate()

Devuelve un array asociativo con parámetros de la fecha actual. Los índices de este array y sus valores son los
que puedes ver en la tabla.

Ejemplos de getdate()
Funcionalidad Sintaxis Devuelve
$s=getdate();
Devuelve un array asociativo Array
echo $s;
Este índice devuelve los segundos de la hora actual echo $s['seconds'] 26
Este índice devuelve los minutos de la hora actual echo $s['minutes'] 56
Este índice devuelve la hora de la hora actual echo $s['hours'] 5
Este índice devuelve el día del mes actual echo $s['mday'] 3
Este índice devuelve el nº del día de la semana echo $s['wday'] 6
Este índice devuelve el nº del mes echo $s['mon'] 10
Este índice devuelve el año echo $s[year] 2015
Este índice devuelve nº del día en el año actual echo $s['yday'] 275
Este índice devuelve el día de la semana echo $s['weekday'] Saturday
Este índice devuelve el nombre del mes echo $s['month'] October

getdate(número)

Interpreta el número como una fecha Unix Each (segundos transcurridos desde el día 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 idénticos
a los de getdate() tal como puedes ver en esta tabla.

Ejemplos de getdate(número)
Funcionalidad Sintaxis Devuelve
$s=getdate(127648);
Devuelve un array asociativo Array
echo $s;
Este índice devuelve los segundos de la hora actual echo $s['seconds'] 28
Este índice devuelve los minutos de la hora actual echo $s['minutes'] 27
Este índice devuelve la hora de la hora actual echo $s['hours'] 12

Pág. 155
Este índice devuelve el día del mes actual echo $s['mday'] 2
Este índice devuelve el nº del día de la semana echo $s['wday'] 5
Este índice devuelve el nº del mes echo $s['mon'] 1
Este índice devuelve el año echo $s['year'] 1970
Este índice devuelve nº del día en el año actual echo $s['yday'] 1
Este índice devuelve el día de la semana echo $s['weekday'] Friday
Este índice devuelve el nombre del mes echo $s['month'] January

time()

Esta función devuelve la hora actual en segundos expresada en tiempo Unix.

<?php print "Han transcurrido ".time(). " segundos desde las cero horas del día 01-01-1970";?> devolvería: Han
transcurrido 1443844586 segundos desde desde las cero horas del día 01-01-1970

microtime()

Esta función devuelve una cadena formada la fracción 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 fracción ".microtime(). " de segundo de la hora actual";?> devolvería: Estamos en la fracción
0.02108100 1443844586 de segundo de la hora actual

mktime (hora, minuto, segundo, mes, día, año)

Devuelve el tiempo Unix de la fecha pasada como parámetro a la función. Es fundamental mantener la secuencia
de los datos. Si se omiten argumentos (sólo pueden omitirse por la derecha) tomará los de la fecha actual.

Cuando el parámetro día es cero devuelve el último día del mes anterior, pero si pasamos cero como parámetro
de mes nos dará un error.

Ejemplos de mktime()
H Min Sec Mes Día Año Tiempo Unix Fecha
23 12 57 6 16 1973 109116777 23:12:57 16-Jun-1973
23 12 57 6 16 1973 109116777 23:12:57 16-Jun-1973
25 12 57 6 16 1973 109123977 01:12:57 17-Jun-1973
23 97 57 6 16 1973 109121877 00:37:57 17-Jun-1973
23 12 57 14 16 1973 130284777 23:12:57 16-Feb-1974
23 12 57 14 0 1973 128902377 23:12:57 31-Jan-1974

En los ejemplos de esta tabla puede verse cómo para valores fuera de rango (mes mayor de 12, minutos mayor
de 60, etcétera) la función realiza la corrección correspondiente.

¡Cuidado!

En versiones anteriores a PHP 5.3.3 la función mktime incluía un séptimo parámetro (que se agregaba
detrás de valor año) relativo a horarios de verano ó invierno.
Ese parámetro era 0 si la fecha corresponde a horario de invierno y 1 ó -1 (según versiones) en el caso de
horario de verano. Actualmente esa opción es considerada obsoleta por PHP. Por esta razón no usamos
ese séptimo parámetro en nuestros ejemplos.

Pág. 156
Funciones de calendario

Los distintos calendarios

Días julianos

El sistema de días julianos fue creado por Joseph Justus Scaliger en 1582 y fue llamado así en recuerdo de su
padre, Julius Cesar Scaliger. Se trata de un sistema de cuenta de días que tiene su origen en el 1 de Enero del año 4713
a.C. y que acabará el 31 de Diciembre de 3267. Este ciclo es producto de multiplicar tres ciclos menores: uno de 28 años
denominado solar, otro de 19 años, que incorpora las fases lunares y uno de 15 años denominado de indicción.

El día juliano es el número resultante de contar los días transcurridos desde la fecha definida por Scaliger como
comienzo del ciclo.

Calendario juliano

El emperador romano Julio Cesar ordenó en el año 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 asesoría de Sosígenes de Alejandría fijó
la duración de cada año en 365,25 días, insertando un día suplementario –en febrero– cada cuatro años, -bis sextus
dies ante calendas Martii- (dos sextos días antes de las calendas de marzo), haciendo bisiestos a todos los años cuyo
número 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
adaptación de fijar la fecha de referencia de la cuenta de años en el nacimiento de Cristo. Pero dado que la duración real
del ciclo de translación de la tierra alrededor del sol es de 365,2422 días solares medios, el calendario juliano –con años
de 365,25 días– empezaba a acumular un error importante.

El Papa Gregorio XIII realizó la corrección en el año 1582. Se descontaron diez días y es por eso que en 1582,
al cuatro de octubre le siguió el día quince (viernes).

Para evitar sucesivos desfases se modificaron las condiciones de los años bisiestos que, en lo sucesivo, habrían de
cumplir la condición de que su ordinal sea divisible por 4 y que no acabe en 00 con la excepción de los múltiplos de
400 que tendrían condición bisiestos.

Calendario judío

La era judía comienza a contar desde un supuesto año de la creación del mundo, que se calcula sumando las
edades de las distintas generaciones mencionadas en la Biblia. El año judío se corresponde con el cristiano sumándole a
éste 3.760 años.

El año judío es solar como el cristiano, pero sus meses son lunares, por lo que cada dos o tres años tiene que
añadirse un mes bisiesto para adecuar al año solar el cómputo de los meses lunares.

Calendario republicano francés

El Calendario Republicano fue adoptado por la Convención Francesa partiendo de las propuestas técnicas
formuladas por el matemático Lagrange. Es un intento de adaptar el calendario al sistema decimal y eliminar referencias
religiosas.

El comienzo del año coincidía con el día 22 de Septiembre, equinoccio de otoño, y se fijó su día uno del año uno el 22 de
Septiembre de 1792, día de la proclamación de la República.

Consta 12 meses de 30 días, a los que se añaden cinco días complementarios (seis en los años que son divisibles
por 4 y no por 100) que son festivos y no se asignan a ningún mes. Los meses se dividen en tres décadas de 10 días. El
calendario fue de aplicación civil en Francia y sus colonias americanas y africanas hasta 1806.

Funciones PHP para el manejo de calendarios

PHP dispone de una serie de funciones que permiten convertir fechas según los distintos calendarios. Son estas:
Pág. 157
gregoriantojd(mes,día,año)

Realiza la cuenta de días julianos correspondiente a la fecha gregoriana pasada en los


parámetros mes, día y año.

El script <?php echo gregoriantojd (9, 27, 1999) ?> nos devolverá: 2451449 que es el día 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 día juliano
correspondiente a la fecha actual. Así que, para tu conocimiento y efectos pertinentes, hoy día 3 -10-2015 estamos
celebrando el día juliano número 2457299.

jdtogregorian(nº de días julianos)

Esta función devuelve en fecha gregoriana –con formato: mes, día y año– el día juliano pasado como parámetro.
Por si quieres ir preparando las celebraciones del 2.500.000 día juliano debes saber que coincidirá con la fecha 8/31/2132

jdtojulian(nº de días julianos)

Con esta función puedes obtener la fecha juliana a partir de un valor de la Cuenta de Días Juliana .
Este script <?php echo jdtojulian(gregoriantojd (date("n"), date("j"), date("Y"))) ?> nos devuelve la fecha actual según el
calendario julianoque es 9/20/2015 según el calendario juliano.

juliantojd(mes,día,año)

Convierte a Cuenta de días Julianos la fecha pasada (mes, día y año) del calendario juliano. Por ejemplo <?php
echo juliantojd(7,25,2011) ?> nos devolverá 2455781 que corresponde a la cuenta de días correspondiente a la
fecha 25/7/2001 expresada según el calendario juliano.

jdtojewish(nº de días julianos)

Esta función nos devuelve la fecha (mes, día y año) según el calendario judío a partir de una fecha expresada
en días julianos.
<?php echo jdtojewish (gregoriantojd (date("n"), date("j"), date("Y"))) ?> nos dará la fecha actual según el calendario
judío que es: 1/20/5776.

jewishtojd(mes,día,año)

Nos devuelve el día juliano correspondiente a una determinada fecha del calendario judío. Por ejemplo: <?php
echo jdtogregorian(jewishtojd(7,21,5758)) ?> nos devolverá 3/19/1998 que es la fecha gregoriana correspondiente al día
21 del séptimo mes del año 5758 según el calendario judío.

jdtofrench(nº de días julianos)

Esta función nos devuelve la fecha según el calendario republicano francés correspondiente al día juliano
especificado como parámetro. <?php echo jdtofrench (gregoriantojd (5, 7, 1796)) ?> nos dará la fecha del calendario
republicano francés que se corresponde con el 7 de Mayo de 1796 (gregoriano) que según parece es: 8/18/4.

Sólo convierte fechas comprendidas entre los años 1 y 14 (fechas Gregorianas del 22 de septiembre de 1792 al
22 de septiembre de 1806) que se corresponden con el período de vigencia oficial de este calendario.

frenchtojd(mes,día,año)

Convierte una fecha del calendario republicano francés en su equivalente en días julianos. Por ejemplo: <?php
echo jdtogregorian(frenchtojd(6,7,8)) ?> nos devolverá 2/26/1800, que es la fecha gregoriana correspondiente al día 7
del sexto mes del año 8según el calendario republicano francés. Igual que la función anterior sólo convierte fechas
comprendidas entres los años 1 y 14 del calendario francés.

jdmonthname(día juliano, calendario)

Pág. 158
Devuelve del nombre del mes correspondiente al día juliano en el calendario señalado.

Ejemplos de jdmonthname()
Fecha Gregoriano Juliano Republicano
Gregoriano Juliano Judío
gregoriana abreviado abreviado francés
3/1/1803 Jan January Dec December Tevet Nivose
3/2/1803 Feb February Jan January Shevat Pluviose
3/3/1803 Mar March Feb February AdarI Ventose
3/4/1803 Apr April Mar March Nisan Germinal
3/5/1803 May May Apr April Iyyar Floreal
3/6/1803 Jun June May May Sivan Prairial
3/7/1803 Jul July Jun June Tammuz Messidor
3/8/1803 Aug August Jul July Av Thermidor
3/9/1803 Sep September Aug August Elul Fructidor
3/10/1803 Oct October Sep September Tishri Vendemiaire
3/11/1803 Nov November Oct October Heshvan Brumaire
3/12/1803 Dec December Nov November Kislev Frimaire
Parámetro
calendario 0 1 2 3 4 5

Los parámetros señalados en la fila inferior son los correspondientes a los tipos de nombres de mes señalados en
los encabezados de la tabla.

Día de Pascua

El Día de Pascua fue fijado en el Concilio de Nicea (año 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 cálculo se basa en el que desarrolló Dionisio Exiguo en el año 532. Para los
años anteriores a 1753, (calendario Juliano) usa un ciclo simple de 19 años para calcular las fases de la luna. En los años
posteriores a esa fecha (Calendario Gregoriano) se añaden dos factores de corrección que tratan de hacer ese ciclo más
preciso. Mediante la función:

easter_date(año)

Devuelve -en tiempo Unix- la media noche del día de Pascua del año establecido como parámetro. Esta función
sólo es válida cuando los valores del año están comprendidos entre 1970 y 2037 (tiempo UNIX).

El script echo date( "j-n-Y", easter_date(2011)) nos señala que la Pascua del año 2006 ha sido el día 24-4-2011.

easter_days(año)

Devuelve el número de días del período comprendido entre el 21 de marzo y el día de Pascua. Si no se especifica
el año, se asume el actual. No tiene las limitaciones de la función anterior y es aplicable a años fuera del intervalo de
tiempo UNIX.

El script easter_days(2011) nos señala que la Pascua del año 2011 ha sido 34 días después del 21 de Marzo.

¡Cuidado!

Si piensas en la posibilidad de utilizar estas funciones en alguna aplicación concreta que pretendas publicar
en unhosting de la red cerciórate antes de que estén habilitadas.

Pág. 159
La opción INCLUDE

Utilización de ficheros externos

PHP dispone de funciones que permiten insertar en un documento una parte o la totalidad de los contenidos de
otro. Esta opción resulta muy interesante, tanto desde el punto de vista operativo como en lo relativo a la seguridad.

Estos son algunos de los recursos que permiten ese tipo de inclusiones:

include("nombre del fichero")

El parámetro nombre del fichero es una cadena que contiene el path y el nombre del fichero cuyos contenidos
pretendemos incluir. Pueden incluirse ficheros con cualquier extensión aunque es muy habitual utilizar archivos con
extensión .inc.php.

La primera parte (inc) nos permitirá identificar este tipo de ficheros mientras que la extensión php obligaría a que
(si un usuario malicioso pretende visualizar el contenido del fichero) fuera interpretado por PHP y, como consecuencia de
ello, solo devolvería el resultado sin permitir la visualización de informaciones privadas (contraseñas 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 función PHP, ni tampoco ningún script de este lenguaje. Lo hemos guardado con dos
extensiones: ejemplo1.inc.php y ejemplo1.inc.

Si pulsas sobre las opciones Ver ejemplo podrás comprobar que los resultados de visualización son distintos
dependiendo de la extensión de cada fichero.

<h3><font color="#ff0000">Este sería un texto


que se incluiría dentro de la página
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á, además, 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
produciría un error por duplicidad en los nombres de las funciones. Como verás en el ejemplo, es posible incluir cualquier
tipo de funciones tanto las de la forma:

<?php function nombre { ?>


.....
... código HTML ...
......

<?php } ?>

con las que se pueden incluir porciones de código HTML en cualquier script, como las del tipo:

function nombre {
.....
... instrucciones PHP ...
......
}

que permiten invocar funciones repetitivas a partir de cualquier documento PHP.

Pág. 160
<?php
function Encabezado() { ?>
<html>
<head>
<title>
Pruebas con la función 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 function Calcula($a,$b) {


return $a*$b;
} ?>

Ver ejemplo2.inc Ver ejemplo2.inc.php

Definidas las funciones en el fichero a incluir y colocado al comienzo de la página 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 ejecución de la función.

Como es lógico, solo serán visualizados en el navegador del cliente los resultados de la ejecución de las funciones
que hayan sidoinvocadas.

<!-- empezaríamos incluyendo el fichero que contiene


las funciones. No escribiría nada hasta que las
funciones que contiene no fueran invocadas //-->
<?php include("ejemplo2.inc.php") ?>
<!-- Insertaremos un script PHP que invoque
la función encabezado. Debe llevar las etiquetas
de apertura y cierre <?php y ?> de PHP //-->
<?php Encabezado() ?>
<!-- Insertaremos código HTML
según nuestra conveniencia //-->
Aquí iría el contenido de la página<br>
.... esto es texto HTML................<br>
...........................<br><br><br>
<!-- Incluimos el fichero ejemplo1.inc.php y dado que no contiene
ninguna función, insertará aquí todo su contenidos //-->
<?php include("ejemplo1.inc.php") ?>
<!-- Insertaremos más código HTML -->
....................<br>
...........................<br><br><br>
<!-- Incluimos nuevamente el fichero ejemplo1.inc.php Puede repetirse
la inclusión porque no contiene funciones,
si las contuviera habría un conflicto de duplicidad
porque una funcion no puede estar definida dos veces
con el mismo nombre. La instrucción include
como en todos los casos deberá ir dentro de un script PHP
y por tanto entre <?php y ?> //-->

Pág. 161
<?php include("ejemplo1.inc.php") ?>
<!-- Ahora ejecutaremos la funcion PHP Calcula() pasando como
parámetros 7 y 9. El return de la función nos devolverá
el resultado que imprimiremos aquí //-->

<?php print "Aquí va el resultado de la multiplicación: ".Calcula(7,9); ?>


<!-- Por último invocaremos la función Pie() -->
<?php Pie() ?>

Ver ejemplo162.php

La función require()

Tiene la misma sintaxis que include y una funcionalidad similar, aunque con algunas diferencias. Igual que ocurría
con aquél, cuando un fichero es invocado por require esa llamada lo que hace es sustituirse a sí misma por el contenido
del fichero especificado.

A diferencia de include, la etiqueta require lee y escribe –en el documento a partir del que es invocada– el archivo
referenciado completo y no acepta condicionales que sí son aceptados por include.

Evitar errores por duplicidad de llamadas

Tanto en el caso de usar la instrucción include como con require, si se intenta incluir dos o más veces un fichero
que contenga funciones, se producirá un error (PHP no permite que dos funciones tengan el mismo nombre) y se
interrumpirá la ejecución del script.

Los errores de ese tipo pueden evitarse usando las funciones:

include_once("fichero")
y
require_once("fichero")

que a diferencia de include y requiere van a impedir que un mismo fichero pueda incluirse dos veces.

En los ejemplos vas a poder comprobar que no aparece el mensaje de error cuando se utiliza esta función y que el
texto que –anteriormente– era incluido dos veces ahora solo aparece una vez.

<!-- Repetimos la inclusión de ambos ficheros


pero veremos que no aparece mensaje de error
por duplicidad de funciones y además
pese a hacer una doble inserción de ejemplo1
solo se visualiza una vez por efecto del filtro
establecido por include_onde //-->
<?php include_once("ejemplo2.inc.php") ?>
<?php Encabezado() ?>
Aquí iría el contenido de la página<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 idéntico al anterior. Sólo hemos sustituido include_once por require_once,
que tiene una funcionalidad similar a la anterior.

Pág. 162
<?php require_once("ejemplo2.inc.php") ?>
<?php Encabezado() ?>
Aquí iría el contenido de la página<br>
....................<br>
...........................<br><br><br>
<?php require_once("ejemplo1.inc.php") ?>
....................<br>
....nada de aquí en adelante ...<br><br><br>
<?php require_once("ejemplo2.inc.php") ?>
<?php require_once("ejemplo1.inc.php") ?>

Ver ejemplo164.php

Comprobando los ficheros incluidos

PHP dispone de dos funciones que permiten recoger en un array la lista de ficheros que se han insertado en el
documento por medio de alguna de las instrucciones: require_once, require, include_once e include. Tales funciones
son estas:

$v=get_included_files()

Recoge en un array escalar (contenido en la variable $v) los nombres de los ficheros incluidos en el archivo en
uso por include_once.

$v=get_required_files()

Igual que la función anterior recoge en un array escalar (contenido en la variable $v) los nombres de los ficheros
incluidos en el archivo en uso mediante require_once.

<?php include_once("ejemplo2.inc.php") ?>


<?php Encabezado() ?>
<?php include_once("ejemplo1.inc.php") ?>
<?php Pie() ?>

Lista de fichero utilizados por include

<?php
$z= get_included_files();
foreach($z as $clave=>$valor) {
echo "Clave: ",$clave," Valor: ",$valor,"<br>";
};
?>

Ver ejemplo165.php

Mejorando la seguridad

Hemos hablado de la función show_source, que permitía visualizar el código fuente de los scripts –no solo locales
sino de cualquier URL- si esta función no estaba desactivada en el php.ini.

Esa posibilidad de ver no sólo permite el espionaje industrial (ver la técnica de construcción de los scripts, etcétera)
sino que permite ver también las claves y contraseñas de acceso a las bases de datos que pudieran contener los scripts.

Pág. 163
Aparte de simplificar el trabajo la opción de incluir ficheros externos permite guardar la información
confidencial fuera del root del servidor y usarla mediante estas llamadas. De ese modo –show_source– permitiría
visualizar el nombre de ese fichero externo pero no su contenido.

Si creáramos un directorio –por ejemplo como subdirectorio de c:\Apache (fuera del root del servidor)– y le
ponemos como nombre sg, podríamos guardar allí los ficheros ejemplo2 y ejemplo1, con lo cual sus contenidos no serían
visibles con show_source.

En este caso la instrucción include ha de contener el path y sería 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, etcétera) requieren utilizar /.
Para publicar tus páginas en un hosting no Windows tendrías que modificar tus scripts. Tenlo en cuenta

Utilizando include para gestión de fechas

Las funciones que incluye PHP para el manejo de fechas solo contemplan periodos posteriores a 1970. Para el
caso de fechas anteriores a esta, existen funciones que pueden descargarse desde: http://phplens.com/lens/dl/adodb-
time.zip.

El archivo comprimido contiene un fichero -adodb-time.inc.php- con funciones PHP que se comportan de forma
idéntica a las nativas de PHP y que, además, permiten utilizar fechas anteriores a 1970 y valores negativos del tiempo
Unix.

Para utilizar estas funciones bastaría con poner en el script include("adodb_time.inc.php"); y sustituir las funciones
de fecha de acuerdo con lo que se indica en esta tabla:

Función PHP Función Adodb-time

getdate() adodb_getdate()
date() adodb_date()
gmdate() adodb_gmdate()
mktime() adodb_mktime()

En este enlace puedes comprobar los resultados de la aplicación de estas funciones que, como verás, son idénticos 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.

Pág. 164
Manejo de ficheros externos

Utilización de ficheros externos

PHP dispone de funciones mediante las cuales se pueden crear, modificar, borrar y leer ficheros de cualquier
tipo así como extraer información sobre ellos y sus contenidos.

Abrir o crear ficheros

Para crear o modificar ficheros se utiliza la instrucción:

$f1=fopen(fichero,modo)

dónde $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 extensión) 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 parámetro.

Valores del parámetro modo de la función fopen


Valor Funcionalidad
r Abre el fichero en modo lectura y coloca el puntero al comienzo del fichero

r+ 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 tamaño a cero y si el fichero no existe intenta
w crearlo
Abre el fichero en modo lectura y escritura y coloca el puntero al comienzo del fichero, reduce su tamaño a cero y si el fichero no
w+ existe intenta crearlo

a Abre el fichero en modo escritura y coloca el puntero al final del fichero y si no existe intenta crearlo

a+ 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 intrucción:

fclose($f1)

Esta función -que devuelve un valor booleano- permite cerrar el fichero especificado en $f1 que, como recordarás,
es el valor delidentificador de recurso que le fue asignado automaticamente por PHP en el momento de la apertura.

Punteros internos

Pág. 165
PHP dispone de funciones para situar sus punteros internos y también para determinar la posición 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 señala 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, posición)

Sitúa el apuntador del fichero señalado por el identificador del recurso $f1 en la posición (expresada en bytes)
señalada por posición.

ftell($f1)

Devuelve (expresada en bytes) la posición actual del puntero interno del fichero.

¡Cuidado!

Antes de utilizar funciones es necesario que el fichero que señala el identificador de recursos haya
sido abierto.

Lectura de ficheros

La lectura de los contenidos de un fichero puede hacerse de dos maneras: sin apertura previa o con apertura
previa del mismo.

Lectura de ficheros sin apertura previa

Las funciones que permiten la lectura de ficheros sin haber sido abiertos previamente son las siguientes:

$t=file_get_contents(fichero)

Recoge en la variable $t el contenido del fichero cuyo nombre y eventual ruta se especifican en el
parámetro fichero.

readfile(fichero)

Escribe directamente en el punto de inserción del script el contenido completo del fichero.

¡Cuidado!

La función 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, además de su contenido añadirá un número que indica
el tamaño del fichero expresado en bytes.

Pág. 166
$var=file(fichero)

Crea $var –un array escalar– cuyos elementos tienen como valores los contenidos de cada una de las líneas del
fichero. Una línea termina allí donde se haya insertado un salto de línea en el fichero original.

Lectura de ficheros con apertura previa

Para la utilización de estas funciones los ficheros han de ser abiertos en un modo que permita la lectura.

fpassthru($f1)

Hace la lectura completa del fichero. Esta función presenta algunas peculiaridades importantes:

 • Cierra el fichero de forma automática después de la lectura. Por esa razón, si se escribe la función fclose a continuación
defpassthru, se produce un error.
 • Si el resultado se recoge en una variable, o si va precedido de echo, además de escribir el contenido del mismo, añadirá
el número de bytes que indican su tamaño.
fgets($f1,long)

Extrae del fichero señalado por el $f1 una cadena –que comienza en la posición actual del puntero– y
cuya longitud está limitada por el menor de estos tres valores:

 • El valor (en bytes) indicado en long.


 • La distancia (también en bytes) desde la posición actual del puntero hasta el final del fichero.
 • La distancia que hay entre la posición actual del puntero y el primer salto de línea.
fgetc($f1)

Extrae el caracter siguiente al señalado por la posición actual del puntero.

Escribir en un fichero

Una vez abierto un fichero -en modo que permita escritura- la función 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
número máximo de caracteres que han de insertarse. Si la cadena de texto tiene menor o igual longitud que el
parámetro long la escribirá en su totalidad, en caso contrario sólo escribirá el número de caracteres indicados.

fputs($f1,"texto",long)

Es un alias de la función anterior.

file_put_contents(nombre_fichero,$cadena)

Crea un fichero cuya ruta, nombre y extensión se definen mediante la cadena nombre_fichero e incluye en él el
contenido de la variable$cadena. Esta función es idéntica a llamar a fopen(), fwrite() y fclose() sucesivamente para escribir
información en un archivo.
Pág. 167
¡Cuidado!

Estas funciones realizan la inserción de la cadena a partir de la posición a la que apunte el puntero en el
momento de ser invocadas.
Si el fichero ya existiera y contuviera datos los nuevos datos se sobrescribirían sobre el contenido anterior.

Para poder añadir contenidos a un fichero el puntero deberá apuntar el final del fichero preexistente y
estar abierto en un modo que permita añadir contenidos.

Borrado de ficheros

Para borrar ficheros se utiliza la siguiente instrucción:

unlink(fichero)

Dónde fichero ha de ser una cadena que contenga el nombre y la extensión del fichero y, en su caso, también el
path.

Duplicado de ficheros

La función:

copy(fichero1, fichero2)

Copia el fichero fichero1 (debe indicarse nombre y extensión) en otro fichero cuyo nombre y extensión se
establecen en la cadenafichero2. Esta función devuelve un valor booleano indicando si la copia se ha realizado con éxito
TRUE (1) o FALSE (nul) si por alguna razón no ha podido realizarse la copia.

Renombrar ficheros

La función:

rename(fichero1, fichero2)

cambia el nombre del fichero fichero1 (hay que poner nombre y extensión) 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 información sobre ficheros. Algunas de ellas son las siguientes:

file_exists(fichero)

Esta función devuelve TRUE si el fichero existe, en caso contrario devuelve FALSE.

filesize(fichero)

Devuelve el tamaño del fichero expresándolo en bytes. En caso de que el fichero no existiera nos dará un error.

filetype(fichero)

Pág. 168
Devuelve una cadena en la que se indica el tipo del fichero. En caso de que el fichero no existiera nos dará un
error.

filemtime(fichero)

Devuelve –en tiempo Unix– la fecha de la última modificación del fichero.

stat(fichero)

Devuelve un array que contiene información 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 línea):

Esto es un ejemplo para comprobar


si funcionan o no los saltos de línea
en un documento de texto
que será leído desde php

En la tabla puedes ver los contenidos asociados a cada uno los índices del array que contiene resultado de aplicar
la función stat al fichero domingo.txt.

Indice Significado Sintaxis Resultado


0 Dispositivo <? echo $d[0] ?> 2056
1 I node <? echo $d[1] ?> 7481717
2 Modo de protección de I node <? echo $d[2] ?> 33279
3 Número de enlaces <? echo $d[3] ?> 1
4 Id de usuario del propietario <? echo $d[4] ?> 701
5 Id de grupo del propietario <? echo $d[5] ?> 701
*
6 tipo de dispositivo si es un inode device <? echo $d[6] ?> 0
7 Tamaño en bytes <? echo $d[7] ?> 126
8 Fecha del último acceso <? echo $d[8] ?> 1443834381
9 Fecha de la última modificación <? echo $d[9] ?> 1312376374
10 Fecha del último cambio <? echo $d[10] ?> 1346230064
11 Tamaño del bloque para el sistema I/O * <? echo $d[11] ?> 4096
12 Número de bloques ocupados * <? echo $d[12] ?> 8
Los valores señalados con * devuelven -1 en algunos sistemas operativos, entre ellos Windows>

Otras funciones

Existen otras muchas funciones relacionadas con el manejo de ficheros y directorios, así como con los permisos
de acceso, etcétera. Hemos resumido únicamente las de mayor interés.

Si quieres profundizar en este tema a través de este enlace podrás acceder al capítulo del Manual de Referencia
oficial de PHP, en el que se describen las funciones relacionadas con el manejo de ficheros.

Ejemplos del uso de algunas funciones sobre ficheros

<?php
/* abrimos con w+ con lo cual borramos el contenido
y creamos el fichero en el caso de que no existiera */
$f1=fopen("sabado.txt","w+");
# escribimos en el fichero vacío

Pág. 169
fwrite($f1,"Esta es la primera linea que escribimos en el fichero<br>");
#cerramos el fichero
fclose($f1);
echo "<H2>Este es el resultado después del primer fwrite</H2><br>";
include("sabado.txt");
# abrimos con r+ con lo cual sobreescribiremos
# en el fichero preexistente
$f1=fopen("sabado.txt","r+");
# escribimos en al principio del fichero preexistente
# ya que al abrir un fichero en este modo el puntero
# se sitúa al comienzo del fichero
fputs($f1,"Esto se sobreescribe");
#cerramos el fichero
fclose($f1);
echo "<H2>Este es el resultado después del segundo fwrite</H2><br>";
include("sabado.txt");
# abrimos con a+ con lo cual AÑADIREMOS
# al fichero preexistente ya que el modo de apertura
# sitúa el puntero al final del fichero
$f1=fopen("sabado.txt","a+");
# escribimos al final del fichero preexistente
fputs($f1," Esto se añadirá al final<br>");
#cerramos el fichero
fclose($f1);
echo "<H2>Este es el resultado después del tercer fwrite</H2><br>";
include("sabado.txt");
echo "<h2>Leyendo con fgetc</h2><br>";
# abrimos con r+ con lo cual podemos LEER y AÑADIR
# al fichero preexistente
$f1=fopen("sabado.txt","r+");
# leemos el primer carácter del fichero
# ya que el apuntador esta el principio
$z=fgetc($f1);
# imprimimos el primer carácter
echo "He leido el primer carácter: ",$z,"<br>";
/* leemos el segundo caracter del fichero
ya que el apuntador se ha movido a esa posición al leer
anteriormente el primer carácter.
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 carácter: ",$z,"<br>";
/* leemos el siguiente caracter del fichero
ya que el apuntador se ha movido a una nueva posición
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 carácter: ",$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
Pág. 170
fclose($f1);
echo "--------------------------------------------------------------<br>";
?>
<h2>Aqui veremos el contenido (sin etiquetas HTML)de una pagina web</H2>
<?php
# Escribimos la dirección completa de la página que puede ser
# el resultado de unir el valor de la variable $_SERVER['DOCUMENT_ROOT']
# (ruta completa del directorio raíz 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 líneas hasta llegar al final del fichero
while (!feof($f1)) {
$z = fgetss($f1, 1024);
echo $z,"<br>";
}
#Cerramos el fichero
fclose($f1);
#Borramos el fichero antes de salir
unlink("sabado.txt");
?>

Ver ejemplo166.php

Otro ejemplo completando el anterior

<?php
# Abrimos el fichero en modo lectura
$f1=fopen("domingo.txt","r");
# Al anteponer echo a fpassthru
# NOS APARECERÁ AL FINAL EL TAMAÑO DEL FICHERO
echo fpassthru($f1),"<br>";
/* Abrimos de nuevo el fichero
RECUERDA QUE FPASSHRU LO CIERRA AUTOMÁTICAMENTE
DESPUÉS DE EJECUTAR LA INSTRUCCIÓN */
$f1=fopen("domingo.txt","r");
# Este bucle nos escribirá cada una de las
#líneas del fichero
while(!feof($f1)){
$z=fgets($f1,4000);
echo $z,"<br>";
}
# Situamos el puntero
#al comienzo del fichero
rewind($f1);
# Reescribimos el fichero
while(!feof($f1)){
$z=fgets($f1,4000);
echo $z,"<br>";
}
# Situamos de nuevo el puntero
#al comienzo del fichero
rewind($f1);
# Situamos el puntero
#señalando el byte número 15 del fichero
fseek($f1,15);
# Releemos el fichero
#ahora la primera línea estará incompleta
#LE FALTARÁN LOS 15 PRIMEROS CARACTERES
while(!feof($f1)){
$z=fgets($f1,4000);
Pág. 171
echo $z,"<br>";
}
# volvemos el puntero al comienzo del fichero
rewind($f1);
#leemos la primera línea
$z=fgets($f1,4000);
echo $z,"<br>";
# Determinamos LA POSICIÓN ACTUAL DEL PUNTERO
echo ftell($f1),"<br>";
# Cerramos el fichero
fclose($f1);
echo "_________________________________________<br>";
# leemos el fichero y lo presentamos
# en diferentes modalidades
$pepe=readfile("domingo.txt");
readfile("domingo.txt");
echo $pepe, "<br>";
#leemos el fichero y lo recogemos
#en un array
$z=file("domingo.txt");
#Al presentar la variable solo
#nos aparecerá la palabra array
echo $z,"<br>";
# presentamos el contenido del array
foreach($z as $linea=>$texto) {
echo "Linea: ",$linea," Texto: ",$texto,"<br>";
};
# copiamos el fichero con mensaje de resultado
if (!copy("domingo.txt", "otrodomingo.txt")) {
print("Error en el proceso de copia<br>\n");
}else{
print "<br>Fichero copiado con exito";
}
# renombramos un fichero con mensaje de resultado
if (!rename("otrodomingo.txt", "otrolunes.txt")) {
print("Error en el proceso de renombrado<br>");
}else{
print "<br>Fichero renombrado con exito";
}
unlink("otrolunes.txt");
echo "Ultima modificación a las: ",date("h:i:s A",
filemtime ("domingo.txt"))," del día ",
date("j-n-Y", filemtime ("domingo.txt"));
echo "<br>El tamaño del fichero es: ", filesize("domingo.txt"),"
bytes<br>";
echo "<br>El fichero es tipo: ", filetype("domingo.txt")," <br>";
echo "<br>Saldrá un 1 si el fichero existe: ",file_exists("domingo.txt");
?>

Ver ejemplo167.php

Ejemplo de un contador de visitas

<?php
/* comprobamos si existe el fichero contador. Si existe
leemos las visitas registradas e incrementamos su valor en una unidad
Si no existe, registramos 1 como valor de número de visitas*/
if(file_exists("contador.txt")){
/* abrimos el fichero en modo lectura y escritura (r+) con lo que
el puntero se colocará al comienzo del fichero */
$f1=fopen("contador.txt","r+");
# leemos el contenido del fichero
Pág. 172
$visitas=(int)(fgets($f1,10));
# lo aumentamos en una unidad
$visitas++;
# colocamos el puntero al comienzo del fichero para que
# al guardar en nuevo valor sobreescriba el anterior
rewind($f1);
}else{
/*abrimos el fichero en modo lectura y escritura con (w+)
de modo que se cree automaticamente al no existir*/
$f1=fopen("contador.txt","w+");
#asignamos uno como valor a número de visitas
$visitas=1;
}
/* escribimos el número de visitas en el fichero. En cualquiera
de los casos el puntero estará al comienzo del fichero, por tanto
cuando existan valores serán sobreescritos */
fwrite($f1,$visitas,10);
print("Esta página ha sido visitada ".$visitas." veces");
fclose($f1);
?>

Ver contador

Guardar y leer datos transferidos mediante un formulario

Aunque el modo más habitual de guardar información suele ser los servidores de bases de datos (MySQL, por
ejemplo) la utilización de ficheros ofrece interesantes posibilidades de almacenamiento de información.

Este es un ejemplo muy sencillo, en el que mediante un formulario tal como el que aparece en el recuadro puede
transferirse y almacenarse la información en un fichero.

<form name="fichero" method="post" action="escribe.php">


<input type="text" name="nombre">
<input type="text" name="apellido">
<input type="edad" name="edad">
<input type="submit" value="enviar">
</form>

Los datos transferidos mediante un formulario como el anterior podrían 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){
/* añadimos "\r\n" a cada valor para que se inserte
un salto de línea y que cada valor sea recogido en
una línea 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 líneas
hasta encontrar el final del fichero */

Pág. 173
while (!feof($f1)) {
/* vamos leyendo el contenido de cada línea del fichero
y aunque establecemos en 250 el número de carácteres
dado que los saltos del línea aparecerán antes
serán ellos los puntos de interrupción de cada lectura*/
$z = fgets($f1,250);
#presentamos el resultado de las lecturas
echo $z,"<br>";
}
# cerramos el fichero
fclose($f1);
?>

Pág. 174
Transferencia de ficheros

Comprobación de la configuración

Antes de empezar con este tema debemos comprobar cuál es la configuración de nuestro php.ini. Si por alguna
circunstancia los valores no coincidieran con los que tenemos aquí debajo, tendríamos que abrir php.ini y modificar
aquellas directivas. Cuando publicamos en un hosting no tenemos acceso al fichero de configuración php.ini pero sí
podemos conocer su configuración mediante el script info.php.

Recordemos que ese fue nuestro primer script –lo hemos creado y utilizado– para comprobar nuestra instalación
y lo hemos guardado con ese nombre en el root de nuestro servidor –/home/rinconas/public_html– así que podremos
acceder a él escribiendo como direcciónhttp://localhost/info.php.

La abundante lista que nos muestra info.php contiene las siguientes líneas (las podemos localizar fácilmente
porque están ordenadas alfabéticamente), que en nuestro caso –configuración por defecto– tendrán los valores que
vemos en la imagen.

Es imprescindible que file_uploads=On (tal como aparece en la imagen) y resulta muy útil también 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 tamaño máximo (en Mbytes) de los ficheros que
pueden ser objeto de esa transferencia.

Si te apetece, y como simple experimento, podemos cambiar el límite del tamaño máximo de transferencia
poniendo un valor más 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 páginas 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 aún no hemos hablado. En la
etiqueta <form> hemos de incluir –obligatoriamente–method='POST' y ENCTYPE = "multipart/form-data" ya que
no soporta ni otro método ni otra forma de codificación.

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 tamaño
máximo e impedir la transferencia de ficheros que excedan ese tamaño.

<html>
<body>
<form enctype="multipart/form-data" action="ejemplo169.php" method="post">
# con este input "oculto" establecemos el límite máximo
# del tamaño 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>
Pág. 175
</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 automática, y, además, se
recogerán 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: elnombre 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 tamaño 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 líneas más 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 estés utilizando puede ocurrir
que varían 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

Envía un fichero cualquiera –de menos de 2Mb– y verás que el error es 0. Repite el envío, ahora con un fichero
que sobrepase ese tamaño, y comprobarás 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 configuración de php.ini y modificar esos límites de transferencia. Al hacerlo incrementarás o
reducirás el límite máximo de transferencia.

Copia del fichero

Tal como hemos visto, el fichero transferido aún no está en el servidor. Por el momento se encuentra en un
directorio temporal y será preciso hacer una copia en nuestro espacio de servidor. Para este proceso puede utilizarse una
función que ya hemos visto en páginas anteriores:

copy(fichero1, fichero2)

Pág. 176
donde fichero1 sería 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 podría ser un nombre cualquiera asignado en el propio script –podemos verlo en el ejemplo– o el
nombre original del fichero transferido. En este caso habría que recogerlo del elemento del array anterior cuyo segundo
índice es name.

En la cadena fichero2 podría incluirse –recuerda que debes ponerlo entre comillas– un path señalando el directorio
o subdirectorio donde queremos que guarde la copia. De no incluirlo, el fichero se copiaría en el directorio desde el que
se está ejecutando el script.

Sintaxis alternativa

La opción anterior tiene una alternativa, igual de eficiente y mucho más segura. Se trata de:

move_uploaded_file(fich1, fich2)

que tiene la misma utilidad que copy y añade algunas ventajas tales como:

 – Comprobar que el fichero ha sido transferido mediante el método POST e impedir que se copie en el servidor en caso
de no cumplirse esa condición.
 – Si la opción safe mode=on (configuración de php.ini en modo seguro) –por defecto está Off– comprueba, además, que
la transferencia del fichero ha sido realizada por el mismo usuario que hace la petición de ejecución del script, evitando
que alguien,maliciosamente, pueda mover ficheros desde el directorio temporal hasta el espacio de servidor.
 – A diferencia de la anterior esta función mueve el fichero y por lo tanto no queda copia del mismo en el fichero temporal
¡Cuidado!

Al usar esta función bajo Windows conviene indicar en el parámetro fichero2 la ruta absoluta completa junto
con el nombre del fichero ya que –de no hacerlo así– en algunas ocasiones la imagen no será transferida al
directorio desde el que se ejecuta el script.

Mejorando las trasnferencias

Cuando está habilitada la opción de transferencias de ficheros es conveniente –en previsión de sorpresas
desagradables– tomar algunas cautelas. Una de ellas sería limitar la posibilidad de transferencia a determinados tipos de
archivos –imágenes, por ejemplo– impidiendo con ello que pudieran transferirse al servidor ficheros de riesgo, tales como:
ejecutables, virus, etcétera.

Cuando se establece este tipo de limitaciones, PHP comprueba los contenidos de los ficheros sin tomar en
consideración la extensión de los mismos. Con ello se evita el riesgo de que puedan esconderse –cambiando la extensión–
ficheros distintos de los permitidos.

Aquí tienes un ejemplo de script que impide la transferencia de ficheros con extensión distinta a .jpg o .gif.

<?php
/* filtramos el tipo de archivos recibidos
de forma que solo se permitan imagenes en formato
jpg ó gif. Si el fichero transferido tuviera formato
distinto, la función exit() acabaría la ejecución 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();
Pág. 177
}else{
# anidamos este segundo condicional
# para guardar en una variable
# la extensión 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 tamaño de modo que no supere
el máximo establecido en el hidden del formulario
(lógicamente ese valor no puede superar el valor máximo
de la configuración de php, pero si puede ser menor)
y también evitaremos archivos sin contenido,
es decir con tamaño CERO */
if($_FILES['archivo']['size']>$_POST['lim_tamano']
OR $_FILES['archivo']['size']==0){
print "El tamaño ".$FILES['archivo']['size']." excede el límite";
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 sobreescribiría

$nuevo_nombre="foto_abuelita";
# añadámosle la extensión real de fichero que teníamos
# 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 función copy
pasaremos el archivo que está en el directorio temporal
al subdirectorio que contiene el script que estamos
ejecutando. Podríamos 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>";
}

?>

Pág. 178
Funciones de compresión

Herramientas de compresión

Existen varias herramientas para compresión de ficheros. Las más populares son las funciones de la
biblioteca bzip2 de Julian Sewardque generan ficheros comprimidos que se reconocen por su extensión (bz2) y la función
de zlib de Jean-loup Gailly y Mark Adler para leer y grabar archivos comprimidos con extensión gz. En esta página
veremos el uso de la segunda de las opciones. Empezaremos comprobando eninfo.php que la opción está activada.
Deberemos ver algo como esto:

En la versión de PHP que estamos utilizando esta opción se activa por defecto y no es necesario modificar
ningún parámetro enphp.ini.

Funciones zlib para compresión de ficheros

Algunas de esas funciones son estas:

$f=gzopen(fichero,modo, ruta)

Abre el fichero identificado por el parámetro fichero y lo hace en el modo especificado en el


parámetro modo (r o w según se trate de modo lectura o escritura). Cuando se trata del modo de escritura el
parámetro w debe ir seguido de un número comprendido entre cero ynueve que especifica el grado de
compresión pretendido.

El parámetro ruta es opcional y puede contener un valor lógico (cero ó uno). Cuando el valor de este parámetro
es 1 permite incluir en el parámetro 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 parámetro ruta aparecerá un error.

gzclose($f)

Cierra el fichero asociado al identificador de recurso $f. Esta función devuelve TRUE en caso de éxito o FALSE si
se produjera un error.

gzeof($f)

Esta función devuelve 1 (TRUE) en el caso de que el puntero apunte al final del fichero abierto e identificado
mediante $f. También devuelve TRUE en caso de error. Si el fichero estuviera abierto y el puntero apunta a una posición
distinta del final del fichero devolverá FALSE.

gzseek($f,desplaza)

Pág. 179
Desplaza –dentro del fichero identificado por $f– el puntero –a partir de su posición actual– la cantidad
de bytes indicados en el parámetro desplaza.

gztell($f)

Devuelve la posición actual del puntero.

gzrewind($f)

Coloca el puntero al comienzo del fichero

gzread($f, longitud)

Devuelve una cadena -después de descomprimida- de longitud igual a la indicada en el parámetro longitud. La
lectura comienza en laposición actual del puntero y acaba cuando la longitud de la cadena leída y descomprimida sea
igual al valor del parámetro longitud o cuando se haya alcanzado el final del fichero.

gzpassthru ($f)

Esta función escribe en la salida (no necesita la función echo) el contenido del fichero desde la posición actual
del puntero hasta el final del fichero. Como es lógico, si estuviera precedida de gzrewind escribiría el fichero completo.

¡Cuidado!

La función gzpassthru cierra automáticamente el fichero después de escribir su contenido. Si


pones gzclosedespués de esta función te dará error y si quieres seguir utilizando el fichero tendrás que
volver a abrirlo con la funcióngzopen.

gzwrite($f, cadena, long)

Esta función escribe en el fichero comprimido que se identifica por $f la cadena contenida en el parámetro cadena.
Opcionalmente puede llevar el tercer parámetro (longitud) en cuyo caso solo escribirá los primeros longitud bytes de la
cadena. Si el parámetro longitud existe y es mayor que la longitud de la cadena, insertará la cadena completa.

gzputs($f, cadena, longitud)

Esta función es idéntica a gzwrite.

readgzfile($fichero,path)

Esta función abre de forma automática el fichero indicado como parámetro fichero, además lo lee y lo escribe
de forma automáticasin necesidad de usar echo ni ninguna otra función de salida.

Si el fichero no está en el mismo directorio que el script -además de incluir la ruta en la cadena fichero- es necesario
añadir el segundo parámetro -path- con valor 1.

Ejemplo de compresión y lectura de un fichero

En este ejemplo trataremos de utilizar las funciones de compresión comentadas al margen. Si observas las formas
de apertura de los ficheros verás que son similares a las utilizadas para la gestión de ficheros. Los modos de apertura
para escritura son: "w0" a "w9" siendo los valores de cero a nueve los indicadores de los niveles de compresión.
Para lectura debe usarse el modo "r" sin indicar ningún nivel de compresión.

Pág. 180
<?php
# asignamos un nombre al fichero con extensión "gz"
$fichero ='prueba.gz';
# abrimos el fichero en modo escritura (w)
# con el nivel máximo de compresión (9)
$f=gzopen($fichero,"w9",0);
$cadena="Este es el primer bloque de texto que hemos
introducido en el fichero comprimido. ";
$cadena .="Añadimos 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 carácter 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 posición 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 después de leerlo
$f=gzopen($fichero,"r");
echo "<br><i>Aquí estará todo el fichero:</i> ";
gzpassthru ($f);
# la función 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 también 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 daría error
?>

Pág. 181
ejemplo174.php

Utilizando un directorio distinto

El ejemplo anterior está desarrollado para el supuesto que el script y el fichero comprimido estén en el mismo
directorio. Si quieres utilizar estas funciones utilizando ficheros alojados en un directorio distinto, solo tendrás que recordar
que algunas funciones deben incluir el parámetro complementario 1.- Estos son las modificaciones que deberías efectuar:

 – La variable que recoge el nombre del fichero debe incluir el path, por ejemplo: $fichero ='/subdirectorio/prueba.gz'
 – La función gzopen debe incluir el tercer parámetro (path) con valor 1, por ejemplo: $f=gzopen($fichero,"r",1);
 – También las funciones gzfile y readgzfile -que abren automáticamente el fichero- deberán incluir ese valor 1 como
parámetro añadido. Por ejemplo: readgzfile($fichero,1) ó $z=gzfile($fichero,1)

Elección del grado óptimo de compresión

Puede parecer que la condición óptima de compresión sería elegir el nivel 9 y eso es cierto si tomamos únicamente
en consideración el tamaño final del fichero comprimido. Sin embargo no existe una relación lineal entre reducción de
tamaño/nivel de compresión. Sin que pueda considerarse ninguna referencia exacta –la compresión alcanzable depende
del contenido del fichero y en consecuencia no puede establecerse una relación funcional– puede comprobarse
experimentalmente que -aparentemente- a partir del grado 2 la reducción de tamaño del fichero es mínima y que cuando
se aumenta el grado de compresión a niveles máximos (tratándose de ficheros de un cierto tamaño) el tiempo de ejecución
aumenta sustancialmente como consecuencia de la reiteración de la ejecución de los algoritmos de compresión.

Comprimiendo cadenas

Las funciones anteriores permiten la creación, lectura y modificación de ficheros comprimidos. Sin embargo,
existen otras funciones PHP que permiten comprimir cadenas. Aquí tienes algunas de ellas.

gzcompress(cadena, nivel)

Esta función devuelve una cadena comprimida a partir de una original especificada en el parámetro cadena. El
nivel de compresión (valores entre 0 y 9) se especifica en el parámetro nivel. Las cadenas resultantes de esta función
pueden descomprimirse aplicando la funcióngzuncompress que referimos más abajo.

gzdeflate(cadena, nivel)

Se comporta de forma idéntica a la función anterior. La única salvedad parece ser que utiliza un algoritmo de
compresión distinto. Las cadenas resultantes de esta función también pueden descomprimirse aplicando la
función gzdeflate.

gzencode(cadena, nivel, opciones)

Esta función devuelve la cadena cadena comprimida con el nivel especificado en nivel y permite dos opciones de
compresión:FORCE_GZIP ó FORCE_DEFLATE que se pueden especificarse como tercer parámetro (opciones) sin
encerrar entre comillas.

El valor por defecto (cuando no se especifica el parámetro opción) es FORCE_GZIP.

Descomprimiendo cadenas

gzuncompress(cadena)

Con esta función se obtiene la cadena original a partir de la cadena comprimida indicada en el
parámetro cadena siempre que esta hubiera sido comprimida usando la función gzcompress.

Pág. 182
gzinflate(cadena)

Funciona igual que la anterior. La única diferencia es que esta descomprime las cadenas que han sido
comprimidas con gzdeflate.

Ejemplo de compresión y descompresión de cadenas

En este ejemplo utilizamos las tres funciones de compresión de cadenas así como las opciones de descompresión
y lectura de cada una de ellas.

<?php
# creamos una cadena de ejemplo
$cadena="Esta es la cadena a comprimir. Intentaremos que sea larga
porque parece que si la hacemos muy corta en vez de reducirse
su tamaño parece que aumenta. Y como sigue siendo enormemente
grande la cadena comprimida intentaremos hacerla aun mayor
a ver que pasa ";
# comprimimos con la función gzcompress
$c=gzcompress($cadena,9);
echo "<br>".$c;
# descomprimimos con la función gzcompress
$dc=gzuncompress($c);
echo "<br>".$dc."<br>";
# ahora utilizamos la función gzencode
$c1=gzencode($cadena,9,FORCE_GZIP);
echo "<br>".$c1."<br>";
/* el resultado lo guardamos en un fichero con extensión 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 leído
unlink("pepe.gz");
# otra opción de compresión de cadenas utilizando la función
# gzdeflate
$c2= gzdeflate($cadena,9);
echo "<br><BR>".$c2;
# con la función gzinflate podemos descomprimir la cadena
# comprimida generada por gzdeflate
$dc2=gzinflate($c2);
echo "<br>".$dc2;
?>

ejemplo175.php

Funciones para buferización de salidas

ob_start()

Esta función activa la buferización de las salidas generadas por el script de PHP a partir de su activación. Dicho
de otra forma, impide que las salidas generadas por el script se envíen al cliente impidiendo que sean visualizadas en el

Pág. 183
navegador. A partir del momento de activar esa buferización, todas las salidas generadas se almacenan en una variable
específica llamada: ob_get_contents()

ob_end_clean()

Esta función desactiva la buferización iniciada por ob_start y borra los contenidos de la
variable ob_get_contents()

ob_clean()

Esta función vacía el buffer de salida pero sin desactivar la bufferización. Las salidas posteriores a esta función
seguirían siendo recogidas en el buffer.

Cabeceras para transferir información comprimida

Cuando un servidor recibe una petición de una página web el navegador del cliente siempre envía información
sobre su disposición a aceptar diferentes tipos de contenidos. Una de las informaciones que suelen recibirse con
la petición del navegador se refiere a su capacidad para aceptar contenidos codificados y esto suelen hacerlo mediante
el envio de una cabecera que diría algo similar a esto: Accept-Encoding:gzip,deflate o Accept-Encoding: gzip.

Esta posibilidad es una característica común a todas las versiones modernas de los navegadores (es posible que
algunas versiones antiguas no acepten esta codificación) y bastará con que se incluya en la respuesta (el documento
transferido por el servidor al cliente) la cabecera: Header('Content-Encoding: gzip') para que el navegador sepa que
la información llegará codificada y que debe activar -de forma automática- sus mecanismos de traducción de ese tipo de
contenidos.

Algunas limitaciones

En todos estos ejemplos hemos dado por supuesto que los navegadores de los clientes aceptan la codificación
gzip, pero es evidente que si eso no ocurriera la página se visualizaría erróneamente.

Economizando espacio en el servidor

Las opciones de compresión pueden permitirnos un cierto ahorro de espacio de servidor. Las páginas HTML
podrían almacenarse comprimidas y ser llamadas a través de un script de descompresión que permita visualizarlas.

En este ejemplo se efectúa la compresión de una página web (una de las páginas de estos materiales guardada
en formato HTML) cuyo tamaño original es de 57.105 bytes. El fichero comprimido resultante ocupa 12.371 bytes. Como
verás, el fichero se reduce a poco más del 20% del original.

<?
# Creamos una variable "vacia"
$cadena="";
# Abrimos el fichero en modo lectura (r)
$f1=fopen("prueba.html","r");
/* hacemos un bucle para leer el fichero
hasta encontrar el final (feof) y vamos recogiendo
el contenido en la variable */
while (!feof($f1)) {
$cadena .= fgets($f1, 1024);
}
/*comprimimos la cadena con gzencode
con lo cual la propia función añade los "encabezados"
de formato gzip*/
$c1=gzencode($cadena,3,FORCE_GZIP);
/* abrimos un nuevo fichero modo escritura (w)

Pág. 184
con "fopen", es decir como un fichero normal con extensión 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 compresión 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 podría hacerse mediante un script como este:

<?php
#abrimos el fichero comprimido con "gzopen"
$f=gzopen("prueba.html.gz","r");
/* leemos el contenido completo
en forma transparente ya que readgzfile descomprime
la salida*/
readgzfile("prueba.html.gz");
# cerramos el fichero
gzclose($f);
?>

Visualizar fichero
comprimido

Economizando tiempo de transferencia

No solo se puede economizar espacio en el servidor. También es posible enviar comprimidas -desde el servidor
hasta el cliente- las páginas web. En ese caso, será el propio navegador el que interprete la información comprimida y la
presente de una manera transparente. Lo que habremos ahorrado habrá sido tiempo de transferencia pero, igual que
ocurría en el comentario anterior, esa reducción del volumen de información a transferir afecta únicamente al contenido
de la página y no a otros elementos que puede incluir, tales como imágenes, etcétera.

Este es un ejemplo de un script que comprime una página web y la envía comprimida al cliente.

<?php
/* activamos la bufferización de la salida
para que no se presenten los resultados del script
directamente en la página
¡¡Cuidado con no dejar líneas 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 "buferización"
# y borramos el contenido del buffer
ob_end_clean();
# insertamos la cabeceras
# indicando el tipo de contenido y el tamaño

Pág. 185
Header('Content-Encoding: gzip');
Header('Content-Length: ' . strlen($cd));;
# presentamos el contenido (cadena comprimida) que será
# "traducido" automáticamente por el navegador
echo $cd;
?>

Ejecutar script

El ejemplo anterior comprimía el contenido del fichero antes de enviarlo. En este que incluimos a continuación
partimos del supuesto de que la página 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 demás es idéntico 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

Pág. 186
Funciones FTP

Requisitos del sistema

El uso de estas funciones requiere que PHP tenga activada la opción FTP (enabled), que en nuestro caso está
activada en la configuración por defecto, tal como puedes ver a través de tu info.php, que tendrá un apartado idéntico al
que observamos en la siguiente imagen.

Esto en cuanto a PHP. Pero además de esta configuración 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 instalación y configuración hemos descrito en el apartado Servidor de FTP. Antes
de poder utilizar las funciones que aquí describimos deberás tener instalado y activo el servidor FTP que allí se
describe.

Nos conviene tener muy presente que esta versión de PHP parece no admitir localhost como nombre de servidor
(en la versión 4 esto no ocurría) y que por esa razón hemos de referirnos al servidor FTP mediante su dirección 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 página anterior hemos hablado de la manera de transferir información 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 servidorHTTP y un servidor FTP).

En la configuración descrita en la instalación del servidor FTP hemos establecido que ambos servidores tengan
sus root en el mismo equipo, pero esa no es la única opción posible. Es totalmente factible que uno de los servidores
esté alojado en un equipo situado físicamente 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 conexión y pasar el login. El
último sería cerrar la conexión.

Abrir la conexión

$identificador=ftp_connect (host,puerto)

Esta función –en la que host es una cadena con el nombre del servidor FTP (no te olvides de ponerlo entre
comillas) y puerto es el número del puerto a través del cual se efectúa la conexión FTP– abre una conexión 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 conexión que será utilizado por las demás funciones.

«Loguearse»

Utilizaremos este término del argot informático –¿horrible, verdad?– para referirnos al hecho de que el usuario
se acredite comoautorizado en el servidor FTP.

ftp_login($identificador,usuario,contraseña)

Pág. 187
Una vez abierta la conexión es preciso comenzar la sesión utilizando la función ftp_login con los siguientes
parámetros:

 • $identificador, que es la variable en la que se recogía el resultado de ftp_connect.


 • usuario, que es el nombre de usuario.
 • contraseña, que es la contraseña de acceso del usuario.

Esta función devuelve un valor booleano que será 1 en el caso en que se inicie la sesión correctamente o NUL si
no lo hace.

Cerrar la conexión

Mediante la función:

ftp_quit($x)

se cierra la conexión abierta con el identificador indicado en la variable $identificador.

<?php
# conexión con el servidor FTP
if($x=@ftp_connect ("127.0.0.1",21)){
echo "Conexión FTP activada<br>";
}else{
echo "No se activo lo conexión 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";
}
#desconexión
ftp_quit($x);
?>

ejemplo180.php

Gestión de directorios en el servidor FTP

Una vez logueados y con la conexión activa, ya podremos utilizar funciones FTP tales como:

ftp_cdup($identificador)

Nos sitúa en el directorio raíz del servidor FTP.

ftp_pwd($identificador)

Devuelve una cadena con el nombre del directorio actual.

ftp_chdir($identificador, otro_directorio)

Cambia el acceso del directorio actual al especificado por la cadena otro_directorio, en caso de que exista.

Pág. 188
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é vacíoy que sea un subdirectorio del directorio actual.

Información sobre los contenidos de los directorios del servidor FTP

ftp_nlist($identificador, nombre_directorio)

Devuelve una array escalar con los nombres de los ficheros y subdirectorios contenidos en el directorio que se
indica ennombre_directorio. Si se trata del directorio actual, el parámetro nombre_directorio puede especificarse como
una cadena vacía ("").

Si la información se refiere a un subdirectorio del actual bastará con poner su nombre como valor del
parámetro nombre_directorio. En cualquier otro caso nombre_directorio contendrá la ruta completa.

ftp_rawlist($identificador, nombre_directorio)

Igual que la función anterior, ftp_rawlist también devuelve un array escalar, pero en este caso con información
ampliada. Este array detalla, además del nombre del fichero, el tamaño, el tipo, la fecha de la última modificación y
los permisos de lectura y/o escritura.

<?php
if($x=@ftp_connect ("127.0.0.1",21)){
echo "Conexión FTP activada<br>";
}else{
echo "No se activo lo conexión 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

Pág. 189
El resultado de la ejecución del script anterior podría producir una salida similar a esta:

Tal como puedes ver en la imagen, la cadena devuelta por la función 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 carácter 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 tamaño que corresponden a los tres niveles de usuarios habituales en sistemas Unix/Linux
(propietario, grupo y resto de usuarios). Para nuestros propósitos bastará con que consideremos los privilegios del primer
bloque, es decir los del propietario.

El primero carácter de cada bloque sólo 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 visualización de su
contenido.

El segundo de los caracteres (puede ser w ó –) indica, si se trata de un fichero, que está permitida la modificación
del fichero. Cuando se trata de un directorio significa que se pueden añadir o suprimir ficheros.

El tercero de los caracteres indicaría (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 negación del atributo en todas las opciones.

El siguiente carácter, el número 1, está asociado con sistemas Linux/Unix e indicaría el número de vínculos
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 propósitos- son los nombres del
usuario y grupo al que pertenece. A continuación aparece el tamaño del archivo (cero si se trata de un directorio), la fecha
y hora de su creación y el nombre del archivo o directorio.

Transferencia de ficheros

Las transferencias de ficheros pueden realizarse en ambos sentidos.

Desde el servidor FTP hasta el servidor HTTP

Mediante la función:

ftp_get( $identificador, nombre_en_servidor_web, nombre_en_servidor_ftp, modo)

Pág. 190
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 parámetromodo puede contener uno de estos
valores: FTP_ASCII o FTP_BINARY

Desde el servidor HTTP hasta el servidor FTP

Para realizar transferencias en sentido opuesto al anterior se utiliza la siguiente sintaxis:

ftp_put($identificador, nombre_en_servidor_ftp, nombre_en_servidor_web, modo)

Se comporta de forma idéntica a la función 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).

Modificación de ficheros en el servidor FTP

ftp_rename($identificador,nombre_actual,nuevo_nombre)

Cambia el nombre del fichero nombre_actual por el indicado en la cadena nuevo_nombre.

ftp_delete($identificador,nombre_fichero)

Elimina -en el servidor FTP- el fichero indicado en la cadena nombre_fichero.

Información sobre ficheros del en el servidor FTP

ftp_size($identificador,nombre_fichero)

Devuelve el tamaño (en bytes) del fichero que se indica en la cadena nombre_fichero.

ftp_mdtm($identificador,nombre_fichero)

Esta función devuelve la fecha de la última modificación del fichero indicado en la cadena nombre_fichero. Esta
fecha se indica entiempo Unix.

Un ejemplo de uso de las funciones FTP

<?php
# Conexión con el el servidor ftp utilizando su dirección IP
if(!$x=@ftp_connect ("127.0.0.1",21)){
echo "No se activo lo conexión FTP";
exit();
}
# Identificación 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
Pág. 191
partiendo del directorio root del usuario actual.
En caso de error (ruta incorrecta o falta de permisos de accesos
nos daría un mensaje de error. Si el cambio tiene éxito nos indicaría
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 más espacios
que serán 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 tamaño de este fichero es: ".$cont." bytes<br>";
break;
case 8:
print "El nombre del fichero o directorio es: ".$cont."<br>";
break;
}
Pág. 192
}
}
# 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 parámetro (miphp)
al directorio del servidor FTP que se indica
en el segundo parámetro. Le ponemos por nombre lago_enol.jpg */
ftp_put($x, "../miphp/experimento/lago_enol.jpg",
"../miphp/enol.jpg",FTP_BINARY);
# obtenemos el tamaño del fichero transferido
echo "El tamaño de fichero tranferidos es: ",
ftp_size($x,"../miphp/experimento/lago_enol.jpg")," bytes<br>";
/* escribimos la fecha de la última modificación 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 función 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:contraseña@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 guardándolo en una cadena
$cadena=""; // inicializamos la variable con una cadena vacía
$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 conexión con el servidor ftp
ftp_quit($x);
# establecemos un enlace de descarga para el fichero comprimido
Pág. 193
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 atención a los nombres de los directorios y adecúalos a la
configuración 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 configuración del sevidor FTP. Hemos podido
comprobar que, algunas veces, por una extraña razón, aparecen en el fichero de configuración dos líneas
segudas dicendoAllowOverwrite Off y AllowOverwrite On. La configuración correcta es AllowOverwrite
On (para permitir sobreescribir). Bastaría con eliminar la línea marcada con Off (o reemplazar el Off por On)
para solventar el problema.

Pág. 194
Mensajes de correo

Correo electrónico

PHP dispone de una función que permite el envío de todo tipo de mensajes de correo electrónico desde una página
web. Son escasos los hosting que tienen activada esta función. El motivo aducido por muchos de ellos para establecer
esta restricción es el riesgo de abusosmediante los mensajes conocidos como spam. Como siempre, si tu interés
es publicar y tienes necesidad de este servicio, procura consultar sobre la disponibilidad de este servicio.

Requisitos del sistema

La utilización de las funciones de correo electrónico requiere disponer de un servidor de correo electrónico
instalado y activo y la modificación de la configuración inicial del fichero php.ini.

Si no tienes instalado este servidor puedes hacerlo ahora. En la página Servidor de correo tienes detallados ambos
procesos (instalación y modificación de php.ini).

Sintaxis

La forma más simple de la función de correo es esta:

mail(destinatario,asunto,mensaje)

Dónde destinatario es la dirección 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 parámetros de la función.

<?
# insertamos la función mail (rojo) dentro de un condicional
# para tener una confirmación de envio y/o aviso de error
# es algo muy habitual para conocer el exito de la ejecución
# de funciones
if(mail("juan@mispruebas.as", "Mi primer mensaje","Este es el texto")){
print "mensaje enviado";
}else{
print "el mensaje no ha podido enviarse";
}
?>

Mensaje con cabeceras MIME

Una forma más completa es la siguiente:

mail(destario,asunto,mensaje,cabecera)

Como puedes ver, en este caso añadimos un nuevo parámetro a la función (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 parámetro Nombre (¡cuidado, no lleva comillas!) será el nombre del remitente, que aparecerá
en el campoDe: cuando el destinatario reciba el mensaje. Donde dice e-mail es obligado escribir una dirección de
correo que debe ir contenidaentre < y >, tal como puedes ver en el ejemplo.

Pág. 195
 Reply-To: correo
En una nueva línea, y sin cerrar las comillas de la cadena iniciada en el encabezado anterior, podemos indicar
la dirección de respuesta del mensaje. La dirección que escribamos donde dice correo (fíjate que no va entre comillas)
será la dirección a la que se enviará la respuesta si el destinatario una vez recibido tu correo desea responder mediante
la opción Responder de su programa de correo electrónico.
 Cc: correo1,correo2,...
De igual forma que en el caso anterior –en una nueva línea y sin cerrar comillas– podemos incluir en correo1, correo2,
etcétera, 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 opción es idéntica a la anterior en cuanto a su funcionamiento, con la única diferencia de que esas direcciones no
serán 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 versión de PHP con que ha sido
creado.
¡Cuidado!

Debemos insistir en sugerirte una especial atención a la sintaxis de este tipo de scripts.
Los contenidos generados por la función mail deben ser interpretados por el servidor de correo y –tanto en
este caso como en los que veremos a continuación– los requisitos de formato de estos servidores son muy
estrictos.
De no adaptarse exactamente a sus especificaciones pueden producirse efectos extraños tales como: envíos
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 atención la estructura del código.
Fíjate que hemos insertado en líneas diferentes cada uno de los conceptos: From, Reply-To, etcétera y que no hemos
dejado ningún espacio al comienzo de esas líneas.

No es por capricho ni por afán estético. Si insertáramos algún carácter delante de esas líneas se plantearían
problemas en la estructura del mensaje y si no incluyéramos un salto de línea para cada uno de los conceptos también
tendríamos ese mismo problema.

La sintaxis MIME es muy estricta en este sentido. ¡Tengamos mucho cuidado en esto!

Hay otra posibilidad sintáctica –como alternativa a los saltos de línea– ya conocida. Podríamos escribir todo en
una sola línea sustituyendo los saltos de línea 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 línea.

El mismo ejemplo, utilizando variables

Aquí tenemos un ejemplo donde los parámetros de envío proceden de variables PHP. Recordemos que esas
variables pueden transferirse –mediante un formulario– a un script que se encargue de su envío.

Pág. 196
Como puedes observar, hemos puesto las direcciones de los destinatarios de las copias –visibles y ocultas– en
sendos arrays y hemos añadido una función que: lee los array, los une en una cadena separándolos con comas y, por
último, quita la última coma añadida utilizando la función substr.

<?
#variables destinatario, asunto, texto, etc.
$destino="andres@mispruebas.as";
$envia="Andrés 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 añadir las comas de separación
$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 añadir las comas de separación
$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());
?>

Pág. 197
Formatos MIME

Funciones PHP requeridas para el envío de mensajes

Podrás ver a lo largo de los ejemplos de envío de mensajes de correo electrónico algunas funciones raras que
vamos a comentar seguidamente:

uniqid(prefijo,booleano)

Genera un identificador único basado en la hora actual del sistema, expresada en microsegundos y con una
longitud de 13 caracteres. El parámetro prefijo permite establecer una cadena o número (puede ser una cadena vacía)
que se antepone al identificador generado por la función. Opcionalmente permite el segundo parámetro booleano que
debe ser un valor booleano (TRUE ó FALSE) o también 0 ó 1. Cuando este parámetro es TRUE añade al final de la
cadena generada anteriormente otra subcadena numérica -generada aleatoriamente- de nueve dígitos,
que refuerza la unicidad del identificador.

preg_replace(busca, reemplaza, cadena)

Busca en la cadena especificada en el parámetro cadena (que puede ser una cadena o una variable que contenga
una cadena) las subcadenas especificadas en busca (recuerda que debe llevar delante y detrás un carácter delimitador
tal como puedes ver en las expresiones regulares) y sustituye esas subcadenas por el contenido del
parámetro 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>') eliminaría 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 codificación 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 electrónico.

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 número de caracteres
especificados en el parámetro numérico longitud- el contenido de una subcadena indicada en el parámetro separador.
Por defecto -cuando no se especifican los parámetros- longitud es igual a 76 caracteres y el separador es la
cadena \r\n (retorno y salto de línea).

Esta función se utiliza para convertir al formato especificado en la RFC 2045 (especificación para MIME) las
cadenas obtenidas porbase64_encode. Es el formato habitual de los ficheros adjuntos de los e-mail.

Formato de los mensajes de correo electrónico

En la página anterior hemos hablado acerca de la manera de enviar un e-mail y veíamos la forma de insertar el
cuarto parámetro de la función mail para incluir algunos elementos de los encabezados MIME. El formato de los mensajes

Pág. 198
está especificado en una serie de normas conocidas como el MIME (Multipurpose Internet Mail Extensions) en las que se
establecen los contenidos y la sintaxis de las diferentes partes de un mensaje.

Recordemos que la función

mail(destinatario, asunto, mensaje, cabecera)

tiene cuatro parámetros 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 más comentarios que reiterar la necesidad de incluir esos valores (e-mail del destinatario y asunto) bien
directamente, como parámetro en la función, o a través de una variable tal como hemos comentado en la página anterior.

Cabeceras de los mensajes

Los diferentes elementos de la cabecera de un mensaje deben insertarse siempre separados por saltos de
línea bien pulsando Enter o incluyendo la secuencia \n dentro de la misma de línea. No pueden incluirse espacios, ni al
comiezo de las nuevas líneas ni después de \n, y las comillas –que han de contener todo el encabezado– se abren delante
del primero de ellos y no se cierran hasta después de haber escrito el último. Pueden contener lo siguiente:

Date: xxxxx

Date: debe escribirse con esta sintaxis exactamente. El parámetro xxxxx es una cadena que contendrá la fecha
de envío del mensaje y que puede obtenerse a través 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 versión 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 dirección e-mail siguiendo
la sintaxis que se especifica. El nombre, como un elemento independiente y la dirección e-mail dentro de < >.

¡Cuidado!

No debemos poner comillas ni en el nombre del remitente, ni en la dirección e-mail, ni en la fecha, etcétera.

Respecto a Cc: y Bcc: ; Reply-To: y X-Mailer: son válidos los comentarios que hemos hecho en la página anterior.

Si no se especifica lo contrario, los mensajes se envían como texto sin formato, pero existen opciones que
permiten especificar el formato que ha de tener un mensaje. La especificación de un formato obliga a incluir otro elemento
en cabecera del mensaje:

Content-Type:

Este elemento debe ir seguido de la especificación en la que se indique el tipo de contenido. Tiene la
sintaxis: tipo/subtipo. El MIME establece un gran variedad de opciones para este propósito. Hablaremos de dos de ellas:

 text/plain
El text/plain es la opción por defecto y señala que el contenido del mensaje es de tipo texto (text) y del subtipo sin
formato (plain)
Pág. 199
 text/html
Como la opción 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 interés 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 podría 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 según 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 línea aparte (fíjate que en los ejemplos o está en línea aparte o aparece
el \n) debemos incluir el elemento boundary= (sin símbolo de $ delante) y detrás del signo igual una cadena (en este
caso entre comillas) que en principio puede ser una cadena cualquiera que no contenga espacios, aunque lo habitual es
incluirla con el formato que podemos ver en los ejemplos.

El cuerpo del mensaje

En su formato más simple el cuerpo del mensaje contiene únicamente texto, pero cuando se trata
de multipartes deberá contener necesariamente: los separadores de las diferentes partes, los encabezados de cada una
de las partes y sus respectivos contenidos. La secuencia habría de ser de este tipo:

 Separador
 Content-type

– Los tipos y subtipos más habituales son los siguientes. Para incluir textos: los ya
mencionados text/plain y text/html. Para imágenes y según el tipo de imagen: image/jpeg, image/gif. Para
sonidos: audio/basic. Para vídeo: video/mpeg. Para ejecutables, comprimidos y otros ficheros
adjuntos: application/octet-stream.

– En cualquier caso, si quieres utilizar algún otro tipo de archivo puedes consultar en la web las especificaciones del
MIME.

– Aparte de tipo/subtipo puede añadirse a Content-type -en el caso de texto- separado por punto y coma, la
especificación del tipo de alfabeto (charset=) seguida del tipo de codificación (te sugerimos el "ISO-8859-1" que hace
alusión al alfabeto latino).

– Cuando se trata de ficheros adjuntos deberemos poner, después del punto y coma, name= seguido del nombre y
extensión del fichero que se adjunta.
 Content-Transfer-Encoding

– Este apartado del encabezado puede especificar una de los siguientes


codificaciones: 7BIT, 8BIT, BASE64, BINARY,QUOTED-PRINTABLE

– La transferencia codificada en 7bit representa la codificación habitual en el formato ASCII de 7 bits. No permite
caracteres ASCII con un código mayor que 127.

– Quoted-printable constituye una de las alternativas al formato ASCII de 7 bits. Esta codificación suele usarse cuando
la mayoría de los caracteres del mensaje puede escribirse con formato US ASCII de 7 bits. Prevé que los caracteres con
códigos 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 codificación más
recomendable para textos.

Pág. 200
– La codificación en base64 convierte cadenas binarias en cadenas de texto, con lo cual pueden ser enviadas de forma
más segura. Es la forma de codificación habitual de las imágenes y los ficheros exe, zip, etcétera.
 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 aparecerían 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 extensión (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 típico 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.
 Codificación

Una vez recogido en el fichero a transmitir en una variable, el paso siguiente es codificar esa variable.Utilizaremos la
codificación más 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
parámetro texto en la función e-mail.
 Separador
 .....
 otra parte
 ...
 Separador final
¡Cuidado!

La inserción de ficheros adjuntos requiere que éstos estén disponibles en el servidor por lo que, antes de
enviarlos, habrá que subirlos al servidor utilizando un proceso como el que hemos analizado cuando
hablábamos deTransferencia de ficheros.

Las cabeceras MIME de un mensaje

Aquí tienes un ejemplo con los diferentes elementos del encabezado de un mensaje. Como ves, hemos incluido
todos los elementos dentro de la función 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());
?>

Pág. 201
Una forma un poco más depurada del script anterior podría ser esta que incluimos aquí debajo. Sus
particularidades son las siguientes:

 – Recogemos los datos en variables e insertamos en la función mail esas variables


 – La variable $cabecera tiene algunas singularidades:
 – La vamos construyendo añadiendo 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 carácter especial
que indica a PHP un salto de línea imprescindible
<?
# datos del mensaje
$destinatario="juan@mispruebas.as";
$titulo="Cabeceras en variables";
$mensaje="Nueva prueba de cabeceras";
$responder="andres@mispruebas.as";
$remite="andres@mispruebas.as";
$remitente="Otra vez Andres"; //sin tilde para evitar errores de servidor
# cabeceras
$cabecera ="Date: ".date("l j F Y, G:i")."\n";
$cabecera .="MIME-Version: 1.0\n";
$cabecera .="From: ".$remitente."<".$remite.">\n";
$cabecera .="Return-path: ". $remite."\n";
$cabecera .="X-Mailer: PHP/". phpversion()."\n";

if( mail($destinatario, $titulo, $mensaje,$cabecera)){


echo "mensaje enviado";}else{print "el mensaje no ha podido enviarse";
}
?>

Mensaje con contenido alternativo

<?
# creamos la variables "salto" para "mayor comodidad
# un salto es la secuencia retorno de carro-nueva línea
# dos saltos es algo similar pero duplicado

$UN_SALTO="\r\n";
$DOS_SALTOS="\r\n\r\n";

# creamos el remitente, etc. y también la que parte que


# contiene el código 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 podríamos haber puesto "tiburcio"
# generamos un identificador unico utilizando un numero aleatorio
# como "semilla" y luego lo codificamos con la función md5

Pág. 202
$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 = "Date: ".date("l j F Y, G:i").$UN_SALTO;


$cabecera .="MIME-Version: 1.0\n";
$cabecera .="From: ".$remitente."<".$remite.">".$UN_SALTO;
$cabecera .= "Return-path: ". $remite.$UN_SALTO;
$cabecera .="Cc:perico@mispruebas.as".$UN_SALTO;
$cabecera .="Reply-To: ".$remite.$UN_SALTO;
$cabecera .="X-Mailer: PHP/". phpversion().$UN_SALTO;

# AQUÍ DEFINIMOS EL CONTENIDO MULTIPART, fíjate que lo acabamos con ";"

$cabecera .="Content-Type: multipart/alternative;".$UN_SALTO;

# insertamos BOUNDARY (fíjate 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 codificación


# 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 línea


# 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 señalar 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 uniría 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 línea 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;
#añado la cadena que contiene el mensaje
$texto_html .= $mensaje;

# insertamos SOLAMENTE un SALTO DE LINEA


# estamos al funal del mensaje

$texto_html .=$UN_SALTO;
Pág. 203
# unimos ambas cadenas para crear el cuerpo del mensaje

$mensaje=$texto_plano.$texto_html;

# enviamos el mensaje utilizando

if( mail($destinatario, $titulo, $mensaje,$cabecera)){


echo "mensaje enviado ";}else{print "ha habido errores en el envio";
}

?>

Mensaje con ficheros adjuntos

<?
# definimos estas variables igual que en el ejemplo anterior

$UN_SALTO="\r\n";
$DOS_SALTOS="\r\n\r\n";

#incluimos en varias, asunto, un texto en HTML


# remitente, etc. etc.

$destinatario="perico@mispruebas.as";
$titulo="Mensaje con dos fichero adjuntos";
$mensaje="<html><head></head><body bgcolor=\"#ff0000\">";
$mensaje .="<font face=\"Arial\" size=6>Prueba HTML </font>";
$mensaje .="</body></html>";
$responder="andres@mispruebas.as";
$remite="andres@mispruebas.as";
$remitente="Andres otra vez";

# definimos el separador de parte


# con el mismo procedimiento del ejemplo anterior

$separador = "_separador_de_trozos_".md5 (uniqid (rand()));

# insertamos los datos de la cabecera del mensaje

$cabecera = "Date: ".date("l j F Y, G:i").$UN_SALTO;


$cabecera .= "MIME-Version: 1.0".$UN_SALTO;
$cabecera .= "From: ".$remitente."<".$remite.">".$UN_SALTO;
$cabecera .= "Return-path: ". $remite.$UN_SALTO;
$cabecera .= "Reply-To: ".$remite.$UN_SALTO;
$cabecera .="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 haciéndola 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


================================================

Pág. 204
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 más arriba
# simplemente lo añadimos 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 disposición para que pueda ser visualizado
# directamente en el cuerpo del mensajes
# en filename le asignamos el nombre con el que queremos que sea
# recibido por el destinatario
# por ultimo especificamos la codificacion como base64

$adj1 .="Content-Type: image/jpeg;";


$adj1 .=" name=\"casa08.jpg\"".$UN_SALTO;
$adj1 .="Content-Disposition: inline; ";
$adj1 .="filename=\"leoncio.jpg\"".$UN_SALTO;
$adj1 .="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 después

$fp = fopen("casa08.jpg", "r");


$buff = fread($fp, filesize("casa08.jpg"));
fclose($fp);

/* Codificación del fichero a adjuntar


------------------------------------------ */
# codificamos en base 64 y troceamos en lineas de 76 caracteres
Pág. 205
# y añadimos 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 después

$fp = fopen("apachito.zip", "r");


$buff = fread($fp, filesize("apachito.zip"));
fclose($fp);

/* Codificación del fichero a adjuntar


------------------------------------------ */

$adj2 .=chunk_split(base64_encode($buff));

/* Separador final YA NO HAY MAS PARTES


---------------------------------------- */

$adj2 .=$UN_SALTO."--$separador".$UN_SALTO;

/* Unión 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";
}

?>
Pág. 206
Imágenes dinámicas

Imágenes dinámicas

PHP permite la creación dinámica de imágenes. Quiere esto decir que una imagen puede ser presentada en la
página web sin necesidad de ser almacenada previamente en el servidor y, además, con un contenido que puede ser
modificado en cada instante. Esta posibilidad que ofrece PHP puede resultar muy útil a la hora de presentar gráficos
estadísticos ya que permitiría utilizar valores actualesobtenidos, por ejemplo, de una base de datos.

Requisitos del sistema

El manejo de imágenes dinámicas requiere que esté instalada la librería de PHP llamada php_gd2.dll. En la
versión de PHP que estamos manejando se instala por defecto, pero requiere que la configuración de
fichero php.ini tenga activada esta extensión. La hemos activado durante el proceso de configuración de PHP (para
usuarios de Windows) y en instalación de Apache + PHP (para usuarios de Ubuntu).

Podemos probar a abrir este enlace, info.php en el que habremos de encontrar algo similar a lo que ves en esta
imagen:

Si eso ocurre habremos comprobado nuestra configuración es la adecuada para utilizar las funciones PHP de este
ámbito y estaremos en disposición de poder generar imágenes dinámicas.

Formatos GIF

Aunque son abundantes los materiales que aluden a este formato gráfico -incluso en las páginas oficiales PHP-
los formatos GIF sólo funcionan en modo lectura. Parece ser que existe un conflicto sobre los derechos de propiedad
del algoritmo de compresión 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 imágenes PNG (Portable Network Graphic) nos permite seguir disponiendo de un formato gráfico
de difusión gratuita con una funcionalidad similar al GIF en lo que se refiere a transparencias y que junto con la
posibilidad de usar también el formato JPG va a cubrir las necesidades gráficas de esta utilidad de PHP.

Scripts para gráficos estadísticos

Si en algún momento tienes interés en insertar en tus páginas gráficos estadísticos, en esta
direcciónhttp://www.aditus.nu/jpgraph/index.php podrás encontrar una interesante colección de scripts listos para usar,
con licencia gratuita para usos no comerciales.

Pág. 207
Formatos soportados

Formatos de imágenes

Aunque podemos obtener desde info.php información sobre los tipos de imágenes soportados por la versión en
uso de PHP, existe una función que permite determinarlos.

imagetypes()

Devuelve un campo de bits correspondiente a los formatos soportados por la versión de GD que estamos
utilizando. Los formatos de imagen que PHP soporta actualmente son: GIF, JPG, PNG y WBMP. El conocimiento de estas
posibilidades gráficas puede sernos muy útil a la hora de elegir entre los diferentes formatos gráficos disponibles. Aquí
tienes el código fuente de un fichero que permite obtener información sobre los formatos soportados por tu versión 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>";
}

?>

Pág. 208
Creando imágenes

Creación de imágenes dinámicas

Una imagen dinámica es tan sólo un script que contiene las instrucciones para la creación de esa imagen. Para
visualizar una imagen dinámica desde una página web basta con invocar el fichero que contiene el script desde la etiqueta
clásica de inserción de imágenes de HTML

<img src="imgxx.php"> donde imgxx.php será el nombre del script que genera la imagen.

Primera etiqueta

Una vez conocidos los formatos que soporta nuestra versión, ya podemos generar imágenes utilizando cualquiera
de esos formatos. Trabajaremos con dos de ellos: JPG y PNG.

La primera instrucción que ha de contener cualquier script que deba generar imágenes 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 instrucción y sin ninguna línea en blanco que la preceda.
Pondremos siempre estas instrucciones inmediatamente debajo de <? sin que las separe ninguna línea
en blanco.

Creación de imágenes

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 generación de la misma. Estas son las funciones PHP para esos
procesos:

$nombre = imagecreate(ancho, alto)

Con esta función se crea una imagen del tamaño indicado en los parámetros ancho y alto (en pixels) que
será recogida en la variable$nombre. Esta función es idéntica para cualquier formato de imagen.

Envío de imágenes al navegador

Para enviar imágenes al navegador (visualización) se usan funciones diferentes según el tipo de imagen definida
en Header. Si pretendemos que la imagen tenga formato JPG habremos puesto en Header la indicación jpeg (¡cuidado!
observa la sintaxis... jpeg). En este caso la función de visualización será:

Imagejpeg($nombre)

Si se tratara de una imagen en formato PNG (recuerda que debe estar definido en Header) la sintaxis sería:

Imagepng($nombre)

Pág. 209
Eliminando imágenes de la memoria

Para borrar imágenes de la memoria del servidor (que no del navegador) se utiliza la siguiente sintaxis:

Imagedestroy($nombre)

El primer ejemplo

<?php
/* insertamos la cabecera sin ninguna contenido (ni siquiera línea 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

Creación 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 función:

$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 serán números enteros comprendidos entre 0 y 255 y que especifican la intensidad de las
luces roja, verde y azul utilizadas para la obtención del color y donde $nombre es la variable utilizada para la creación
de la imagen por imagecreate

Se pueden definir tantos colores como se deseen tan sólo con utilizar nombres de variables distintos para cada
uno de ellos.

Aplicar colores de fondo

Para aplicar un color de fondo a una imagen (no importa el tipo del formato) se utiliza la siguiente función:

Imagefill($nombre,x,y,$color)

donde $nombre es la variable que contiene la imagen, x e y son las coordenadas del punto de la imagen a partir
del cual se aplica el relleno y $color el color (previamente definido) que se pretende aplicar a la imagen. Mediante esta
función todos los puntos colindantes con el de coordenadas x,y que tengan su mismo color serán rellenados con el color
especificado en la variable $color.

Aquí tienes dos ejemplos de creación 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);

Pág. 210
/* creamos un color de fondo con nombre $fondo */
$fondo=imagecolorallocate ($im, 0, 0, 200);
/* aplicamos el clor al fondo */
Imagefill ($im, 0, 0, $fondo);
Imagejpeg($im);
Imagedestroy($im);
?>

Ver ejemplo193.php

<?php
Header("Content-type: image/png");
$im = imagecreate(200,200);
/* creamos un color de fondo con nombre $fondo */
$fondo=imagecolorallocate ($im, 0, 0, 200);
/* aplicamos el clor al fondo */
Imagefill ($im, 0, 0, $fondo);
Imagepng($im);
Imagedestroy($im);
?>

Ver ejemplo194.php

Figuras

Rectángulos sin relleno

Para dibujar un rectángulo sin relleno (solo las líneas) se utiliza la siguiente función:

imagerectangle($nombre, x0, y0, x1, y1, $color)

Dónde $nombre es el nombre de la imagen, x0, y0 son las coordenadas del vértice superior izquierdo y x1, y1 las
coordenadas delvértice inferior derecho y $color el color que pretendemos asignar a los lados del rectángulo.

El punto (0,0) siempre es la esquina superior izquierda de la imagen y recuerda que las líneas no tienen un color
distinto al del fondo no se visualizará el rectángulo.

<?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);
Pág. 211
Imagedestroy($im);
?>

Ver ejemplo196.php

Rectángulos con relleno

Para dibujar un rectángulo con relleno se utiliza la siguiente función:

imagefilledrectangle($nombre, x0, y0, x1, y1, $color)

Los parámetros son idénticos a los del caso anterior con la única diferencia de que en este caso el rectángulo
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 rectángulo 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 rectángulo anterior insertamos otro coloreado */
imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo);
Imagepng($im);
Imagedestroy($im);
?>

Ver ejemplo198.php

Polígonos con relleno

Para trazar un polígono con un color de fondo son necesarias dos operaciones:

 – Crear un array con las coordenadas de cada uno de sus vértices.


 – Aplicar la función que dibuja polígonos de este tipo.

La creación del array podría hacerse así:

Pág. 212
$vertices=(x0, y0, x1, y1,... xn, yn )

dónde se irían introduciendo las coordenadas de los sucesivos vértices del polígono (x e y de cada vértice).
Una vez creados los vértices aplicaríanos la siguiente función:

imagefilledpolygon($nombre, $vertices, nº vertices , $color)

donde $nombre es el nombre de la imagen, $vertices es el array que contiene las coordenadas de los vértices, nº
vertices es el número de vértices del polígono 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

Polígonos sin relleno

Su funcionamiento es idéntico al anterior en tanto requiere que se defina el array de coordenadas de los vértices
y los parámetros de la función son los mismos indicados en el caso anterior. Sólo se modifica el nombre de la función que
en este caso es:

imagepolygon($nombre, $vertices, nº vertices , $color)

<?php
Header("Content-type: image/jpeg");
$esquinas=array(20,100,100,180,180,100,100,20);
$im = imagecreate(200,200);
$fondo=imagecolorallocate ($im, 0, 0, 200);

Pág. 213
$blanco=imagecolorallocate ($im, 255, 255, 255);
$rojo=imagecolorallocate ($im, 255,0, 0);
$amarillo=imagecolorallocate ($im, 255, 255,0);
Imagefill ($im, 0, 0, $fondo);
imagerectangle ($im, 10, 10, 190, 190, $blanco);
imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo);
imagepolygon ($im, $esquinas, 4, $rojo);
Imagejpeg($im);
Imagedestroy($im);
?>

Ver ejemplo201.php

<?php
Header("Content-type: image/png");
$esquinas=array(20,100,100,180,180,100,100,20);
$im = imagecreate(200,200);
$fondo=imagecolorallocate ($im, 0, 0, 200);
$blanco=imagecolorallocate ($im, 255, 255, 255);
$rojo=imagecolorallocate ($im, 255,0, 0);
$amarillo=imagecolorallocate ($im, 255, 255,0);
Imagefill ($im, 0, 0, $fondo);
imagerectangle ($im, 10, 10, 190, 190, $blanco);
imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo);
imagepolygon ($im, $esquinas, 4, $rojo);
Imagepng($im);
Imagedestroy($im);
?>

Ver ejemplo202.php

Elipses, circunferencias y arcos

Mediante una única función podremos dibujar elipses, circunferencias y arcos. Es la siguiente:

imagearc($nom, Xcentro, Ycentro , a, b, anguloinicial, angulofinal, $color)

Los parámetros de esta función 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 posición angular del radio inicial del arco y se expresa en grados sexagesimales.
 angulofinal es la posición angular del radio final del arco también en grados sexagesimales.
 $color es el color con el que se dibujará la línea.

Respecto a los ángulos, CERO GRADOS coincide con el cero trigonométrico 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);

Pág. 214
$im = imagecreate(200,200);
$fondo=imagecolorallocate ($im, 0, 0, 200);
$blanco=imagecolorallocate ($im, 255, 255, 255);
$amarillo=imagecolorallocate ($im, 255, 255,0);
$rojo=imagecolorallocate ($im, 255, 0,0);
Imagefill ($im, 0, 0, $fondo);
imagerectangle ($im, 10, 10, 190, 190, $blanco);
imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo);
imagepolygon ($im, $esquinas, 4, $blanco);
imagearc ($im, 100, 100, 160, 160, 0, 360, $fondo);
imagearc ($im, 100, 100, 160, 100, 0, 360, $rojo);
imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo);
Imagejpeg($im);
Imagedestroy($im);
?>

Ver ejemplo203.php
<?php
Header("Content-type: image/png");
$esquinas=array(20,100,100,180,180,100,100,20);
$im = imagecreate(200,200);
$fondo=imagecolorallocate ($im, 0, 0, 200);
$blanco=imagecolorallocate ($im, 255, 255, 255);
$amarillo=imagecolorallocate ($im, 255, 255,0);
$rojo=imagecolorallocate ($im, 255, 0,0);
Imagefill ($im, 0, 0, $fondo);
imagerectangle ($im, 10, 10, 190, 190, $blanco);
imagefilledrectangle ($im, 20, 20, 180, 180, $amarillo);
imagepolygon ($im, $esquinas, 4, $blanco);
imagearc ($im, 100, 100, 160, 160, 0, 360, $fondo);
imagearc ($im, 100, 100, 160, 100, 0, 360, $rojo);
imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo);
Imagepng($im);
Imagedestroy($im);
?>

Ver ejemplo204.php

Dibujando sobre una imagen de fondo

PHP permite crear imágenes utilizando como fondo una prEexistente. Para ello es necesario cambiar la
instrucción $nom = imagecreate(x,y) por $nom= imagecreatefrompng (nombre_de_la_imagen_de_fondo) si se trata
de utilizar una imagen con formato PNG o$nom= imagecreatefromjpeg (nombre_de_la_imagen_de_fondo) cuando se
trata de usar una imagen JPG.

La imagen resultante puede tener formato JPG o PNG dependiendo de lo que se especifique en Header y como
formato de salida independientemente del formato que pudiera tener la imagen utilizada como fondo de la composición

<?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);
Pág. 215
imagearc ($im, 100, 100, 100, 160, 0, 360, $rojo);
Imagejpeg($im);
Imagedestroy($im);
?>

Ver ejemplo204a.php
Imagen original PNG
Imagen resultante JPG

Como puedes comprobar en los ejemplos, el tamaño de la imagen es el mismo de la utilizada como fondo.

Guardando imágenes

Las imágenes 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) añadiendo un segundo parámetro con el nombre y la extensión del fichero
que vamos de guardar.

Así por ejemplo: Imagepng($nombre, "mi_imagen.png") o Imagejpeg($nombre, "mi_imagen.jpg") guardarían en


el servidor las imágenes creadas con los nombres mi_imagen.png o mi_imagen.jpg en el directorio actual del servidor.>

¡Cuidado!

No dejes NUNCA líneas en blanco entre la etiqueta <? de comienzo del script y la línea que
contiene Header
Si escribiéramos el script anterior
sustituyendo image/jpeg por image/png e Imagejpeg($im) por Imagepng($im) no visualizaríamos 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.

Utilización de imágenes dinámicas

En todos los ejemplos anteriores hemos podido visualizar las imágenes con sólo llamarlas desde el navegador, de
la misma forma que podríamos visualizar cualquier otra imagen. Pero las imágenes dinámicas pueden ser insertadas en
una página web de la misma forma que cualquier otra imagen.

Aquí tienes un ejemplo donde se recogen en una página web todas las imágenes dinámicas creadas
anteriormente.

ejemplo205.php Ver código fuente

Si observas el código fuente verás 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.

Pág. 216
Imágenes con líneas y textos

Trazando segmentos

La función PHP que permite dibujar segmentos rectilíneos es la siguiente:

imageline($nombre, x0, y0, x1,y1,$color)

donde: $nombre es el nombre de la variable definida mediante imagecreate, x0 e y0 son las coordenadas de uno
de los extremos; x1 ey1 son las coordenadas del otro extremo y $color es la variable de color con el que será dibujada la
línea.

Tal como puedes observar en los primeros ejemplos de esta página, PHP utiliza como fondo de la imagen el primer
color definido por la función: ImageColorAllocate. Esta opción de PHP nos obliga a definir dos colores distintos para
conseguir la visibilidad de las líneas.

Aunque presentaremos únicamente el código fuente de una de las imágenes, para hacer la comprobación de las
funciones y las diferencias de visualización 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("Content-type: 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 Ver ejemplo212.php


Formato PNG Formato JPG

Crear transparencias

Si deseamos que un color determinado se comporte como si fuera transparente debemos utilizar la función:

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 pequeños detalles:

 • Si pretendes lograr un fondo transparente debes hacer transparente el primero de los colores definidos.
 • Esta función sólo tiene sentido en imágenes 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);
Pág. 217
imageline($im,0,0,200,200,$linea);
Imagepng($im);
Imagedestroy($im);
?>

Ver ejemplo213.php Ver ejemplo214.php


Formato PNG Formato JPG

Insertando textos

Para insertar textos dentro de una imagen hemos de recurrir a una de estas funciones:

imagechar ($imagen, tamaño, x, y, $texto, $color)

Requiere que la variable $texto contenga una cadena definida con anterioridad. Mediante esta función se inserta
el primer carácter de la cadena con orientación horizontal. Los parámetros de la función son los siguientes:

 $nombre el nombre de la variable con la que fue definida por imagecreate


 tamaño es un número comprendido entre UNO y CINCO que asigna el tamaño de la letra de menor a mayor.
 x e y son las coordenadas del punto donde se colocará la esquina superior izquierda del carácter a representar.
 $texto es la cadena de texto de la que se extraerá el primer carácter, el único que se verá en la imagen.
 $color es el color del carácter a representar.
<?php
Header("Content-type: image/png");
$im = imagecreate(150,150);
$t1="Tamaño 1";
$t2="Tamaño 2";
$t3="Tamaño 3";
$t4="Tamaño 4";
$t5="Tamaño 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 Ver ejemplo217.php


Formato PNG Formato JPG

imagecharup ($imagen, tamaño, x, y, $texto, $color)

Su funcionamiento es similar al de la función anterior, con la única diferencia de que inserta el carácter con
orientación vertical. Lascoordenadas de inserción también se corresponden con las de la esquina superior izquierda del
carácter pero, recuerda que ahora estará girado y que, por lo tanto, ese punto coincidirá con parte inferior izquierda de la
imagen del carácter.

<?php
Header("Content-type: image/png");
$im = imagecreate(150,150);

Pág. 218
$t1="Tamaño 1";
$t2="Tamaño 2";
$t3="Tamaño 3";
$t4="Tamaño 4";
$t5="Tamaño 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 Ver ejemplo219.php


Formato PNG Formato JPG

imagestring ($imagen, tamaño, x, y, $texto, $color)

Esta función se comporta de forma similar a imagechar. La única diferencia entre ambas es que
mientras imagechar inserta sólo el primer carácter, en el caso de imagestring se inserta la cadena completa. Los
parámetros de ambas funciones son los mismos.

Si la cadena desborda los límites de la imagen sólo se visualizará la parte de la misma contenida dentro de éstos.

<?php
Header("Content-type: image/png");
$im = imagecreate(150,150);
$t1="Tamaño 1";
$t2="Tamaño 2";
$t3="Tamaño 3";
$t4="Tamaño 4";
$t5="Tamaño 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 Ver ejemplo221.php


Formato PNG Formato JPG

imagestringup ($imagen, tamaño, x, y, $texto, $color)

Inserta una cadena completa con orientación vertical y sus parámetros son idénticos a los comentados cuando
nos hemos referido aimagecharup.

<?php
Header("Content-type: image/png");
$im = imagecreate(150,150);
$t1="Tamaño 1";
Pág. 219
$t2="Tamaño 2";
$t3="Tamaño 3";
$t4="Tamaño 4";
$t5="Tamaño 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 Ver ejemplo223.php


Formato PNG Formato JPG

Tipos de letra

Todas las funciones anteriores utilizan siempre la fuente predefinida por PHP y sólo permiten los cinco
tamaños que hemos podido ver en los ejemplos. Afortunadamente –lo veremos en la página siguiente– PHP también
permite usar fuentes TrueType y aplicarlas en la creación de imágenes.

Pág. 220
Manejando fuentes

Utilizando fuentes TrueType

Si has leído los comentarios de la página anterior recordarás que para usar estas funciones es preciso que estén
instaladas las libreríasFreeType y que, además, conozcamos el path de directorio que contiene las fuentes TrueType.

Hemos creado un subdirectorio llamado fuentes y lo hemos incluido en directorio donde están alojadas estas
páginas. En ese subdirectorio hemos incluido dos fuentes TrueType manteniendo en una de ellas el nombre original
(arial.ttf) y renombrado la otra comofuente2.ttf.

Como podrás comprobar en los ejemplos, no hay problema alguno por el hecho de renombrar las fuentes.

Escribiendo con fuentes TrueType

La función PHP que nos permite insertar este tipo de textos en imágenes dinámicas es la siguiente:

Imagettftext($nombre, tamaño, angulo, x, y, $color, $fuente, $texto)

donde:

 $nombre es, como siempre, el nombre de la imagen.


 tamaño es un número entero que indica el el tamaño 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 inserción del texto. Ese punto coincide con la esquina inferior
izquierda del rectángulo imaginario que contiene el texto.
 $color es el color a utilizar en el texto.
 fuente es una cadena de texto que contiene el path y el nombre de la fuente. Observa los ejemplos.
 $texto es el nombre de la variable que contiene el texto a insertar.

Texto True Type horizontal

<?php
Header("Content-type: image/png");
$im = imagecreate(400,300);
$fondo=imagecolorallocate ($im, 255, 255, 210);
$rojo=imagecolorallocate ($im, 255, 0, 0);
$texto="PHP";
Imagettftext($im, 40, 0, 100, 270, $rojo,"./fuentes/fuente2.ttf",
$texto);
Imagepng($im);
imagedestroy($im);

?>

Ver ejemplo224.php Ver ejemplo225.php


Formato PNG Formato JPG

Texto True Type girado

<?php
Header("Content-type: image/png");

Pág. 221
$im = imagecreate(400,300);
$fondo=imagecolorallocate ($im, 255, 255, 210);
$rojo=imagecolorallocate ($im, 255, 0, 0);
$texto="Me gusta PHP";
Imagettftext($im, 40, 30, 100, 270, $rojo, "./fuentes/fuente2.ttf",
$texto);
Imagepng($im);
imagedestroy($im);

?>

Ver ejemplo226.php Ver ejemplo227.php


Formato PNG Formato JPG

¡Cuidado!

Las rutas (path) de la las fuentes utilizadas por Imagettftext pueden darte un montón de quebraderos de
cabeza. Las rutas relativas que ves en estos ejemplos no parecen dar problema alguno. Sin embargo si
hiciéramos 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 solución que parece ser más efectiva es huir como alma que lleva el diablo del uso de variables en la
asignación de rutas de las fuentes. Vamos, ¡escribir la ruta completa a pico y pala!

Colocando los textos

PHP dispone de una función que permite determinar las dimensiones de una caja de texto (el rectángulo
imaginario que rodea el texto).

$rect= ImageTTFBBox (tamaño, angulo, fuente, $texto)

donde tamaño es el tamaño de la fuente a utilizar, angulo es el ángulo de rotación del texto que tendría valor cero en
el caso de orientación horizontal, fuente es el path y nombre de la fuente a a utilizar, $texto es el nombre de
la variable que contiene el texto a incluir.

La variable $rect recoge un array escalar cuyos valores son las coordenadas de las cuatro esquinas de la caja
de texto.

Los índices correspondientes a cada uno de los elementos de ese array son los siguientes:

 – Inferior izquierdo. Sus coordenadas son: $rect[0] y $rect[1]


 – Inferior derecho. Sus coordenadas son: $rect[2] y $rect[3]
 – Superior derecho. Sus coordenadas son: $rect[4] y $rect[5]
 – Superior izquierdo. Sus coordenadas son: $rect[6] y $rect[7]

Respecto a estas coordenadas, habremos de tener en cuenta lo siguiente:

 – Las correspondientes al vértice 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

Pág. 222
Aquí tienes un ejemplo donde utilizando ImageTTFBox e ImageTTFText se puede centrar un texto -tanto si es
horizontal como si está girado- con relación 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, están 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 rectángulo 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 parámetros de la función ImageTTFText los siguientes:

 Abscisa= X - $pepa[4]/2
 Ordenada= Y - $pepa[5]/2

Este procedimiento es válido 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 Ver ejemplo229.php


Formato PNG Formato JPG

Un ejemplo resumen

Aquí tienes un ejemplo bastante completo de generación de imágenes dinámicas.

Ver ejemplo230.php Ver código fuente

Pág. 223
Diagramas de sectores

Diagramas de sectores

Esta posibilidad gráfica de tratamiento de información estadística la proporciona la función

imagefilledarc( Xc, Yc, a, b,anguloi, angulof , $color, tipo )

dónde los parámetros son: Xc y Yc que son las coordenadas del centro de la elipse cuyo arco (o porción) tratamos
de representar. Los números a y b son las longitudes (expresadas en pixels) de los semiejes horizontal y vertical de la
elipse. Si ambos fueran iguales el resultado sería circular. Los parámetros 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 parámetro $color es la variable –ha de ser definida previamente mediante imagecolorallocate– que indica el
color que ha de utilizarse en el gráfico. Por último el parámetro 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 porción de arco, pero no incluye la representación de los
radios en el dibujo. La opcionIMG_ARC_EDGED se comporta de forma idéntica a IMG_ARC_PIE cuando se utiliza de
forma aislada aunque tiene una opción muy interesante que veremos un poco más abajo. Con IMG_ARC_CHORD el
resultado es un triángulo –relleno con el color indicado– formado por los dos radios y la cuerda correspondiente al arco
que delimitan.

Combinar dos constantes de tipo

Cuando en la función imagefilledarc() utilizamos como tipo una expresión tal


como: IMG_ARC_NOFILL|IMG_ARC_EDGED (fíjate en el signo | que separa ambas constantes) lo que obtenemos es la
representación gráfica del contorno del sector (incluye los radios que lo delimitan). Mediante esta opción -con
dos llamadas a la función- tenemos la posibilidad de representar el sector con un color de relleno (usando IMG_ARC_PIE)
y, luego, superponerle un contorno de distinto color. Puedes verlo en los ejemplos.

Efecto tridimensional

Tal como puedes ver en los ejemplos, resulta fácil 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);

Pág. 224
$fondo = imagecolorallocate($im, 226, 226, 226);
$col1=imagecolorallocate($im,255,255,0);
$col2=imagecolorallocate($im,255,0,0);
imagefilledarc($im, 200, 200, 350, 300, 20, 240, $col1, IMG_ARC_EDGED);
imagefilledarc($im, 200, 200, 350, 300, 10, 150, $col2, IMG_ARC_NOFILL);
header('Content-type: image/png');
imagepng($im);
imagedestroy($im);
?>

Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<?php
$im = imagecreate (400, 400);
$fondo = imagecolorallocate($im, 226, 226, 226);
$color1=imagecolorallocate($im,255,0,0);
imagefilledarc ($im, 200, 200, 350, 300, 20, 240, $color1,
IMG_ARC_NOFILL|IMG_ARC_EDGED);
header('Content-type: image/gif');
imagegif($im);
imagedestroy($im);
?>

Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<?php
$im = imagecreate (400, 400);
$fondo = imagecolorallocate($im, 226, 226, 226);
$color1=imagecolorallocate($im,255,0,0);
imagefilledarc ($im, 200, 200, 350, 300, 50, 200, $color1, IMG_ARC_CHORD);
header('Content-type: image/gif');
imagegif($im);
imagedestroy($im);
?>

Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

<?
$im = imagecreate (400, 400);
$fondo = imagecolorallocate($im, 226, 226, 226);
$color1=imagecolorallocate($im,200,0,0);
$color2=imagecolorallocate($im,255,0,0);
$color3=imagecolorallocate($im,255,255,255);
for($i=200;$i<225;$i++){
imagefilledarc($im, 200, $i, 370, 270, 50, 330, $color1,
IMG_ARC_NOFILL|IMG_ARC_EDGED);
}
imagefilledarc($im, 200, 200, 370, 270, 50, 330, $color2, IMG_ARC_EDGED);
imagefilledarc($im, 200,200, 370, 270, 50, 330, $color3,
IMG_ARC_NOFILL|IMG_ARC_EDGED);

header('Content-type: image/gif');
imagegif($im);
imagedestroy($im);
?>

Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Pág. 225
Encuadre y redimensionado de imágenes

Lectura de imágenes externas

La visualización de imágenes no presenta ningún problema –lo hacemos habitualmente mediante etiquetas
HTML– cuando se encuentran en el espacio del servidor, bien sea propio o ajeno. El problema puede surgir cuando
tratemos de almacenar esas imágenes fuera del root del servidor (una forma de impedir la accesibilidad desde otras webs)
y eso puede conseguirse mediante las funciones que veremos en este capítulo.

Se trata de utilizar PHP para hacer una copia de la imagen original. Para ello debemos conocer la ubicación de
aquella y también sufomato. A partir de esos datos ya solo nos quedaría utilizar una de las funciones:

$copia=imagecreatefromjpeg($original)
o
$copia=imagecreatefrompng($original)
o
$copia=imagecreatefromgif($original)

que nos permitiría crear una copia de la imagen original utilizando la función adecuada al formato de aquella
(jpg, png o gif). La visualización 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 requeriría una de las
opciones imagecreatefromjpeg, imagecreatefrompng ó imagecreatefromgif según sea el formato de la imagen
original.
 image..($copia) que ahora requeriría una de las
opciones imagejpeg($copia), imagepng($copia) ó imagegif($copia) según 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 sería preciso que estuviera en el root del
servidor.
Podría 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 extensión 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 función adecuada */
switch($tipo){
case "jpg":
$copia=imagecreatefromjpeg($original);
break;
case "png":
$copia=imagecreatefrompng($original);

Pág. 226
break;
case "gif":
$copia=imagecreatefromgif($original);
break;
}
/* visualizamos la imagen ateniendonos al formato establecido en Header */
imagejpeg($copia);
/* eliminamos la imagen de memoria */
ImageDestroy($copia);
?>

Ver ejemplo .jpg Ver ejemplo .png Ver ejemplo .gif

Redimensionar y recortar de imágenes externas

Puede parecer que esta posibilidad carece de utilidad. A fin de cuentas, con etiquetas HTML podemos asignar el
ancho y el alto de una imagen. Pero enseguida veremos que esta opción no es tan trivial como parece. El objetivo es
obtener una imagen con unas dimensiones determinadas y unos márgenes también establecidos a partir de una parte (o
el todo) de un original.

La imagen resultante tiene bordes en blanco y además contiene el


Copia de la imagen original. Pretendemos recortar la parte marcada
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 después de haberla deformado para adaptarla a unas nuevas dimensiones. Para
lograr este propósito va a ser necesario que utilicemos estas funciones:

$dimensiones=getimagesize($original)

dónde $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)

dónde $ampliacion es el identificador de una nueva imagen –en blanco– creada en color verdadero con
dimensiones x e y

Pág. 227
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 fotografía. Si queremos una foto a sangre pondremos 0,0 y, si quieres
dejar márgenes en blanco, habrá que poner los anchos de esos márgenes (izquierdo y superior)
respectivamente. Xcopia e Ycopia nos servirán 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 márgenes (izquierdo y superior)
no podrán ser mayores que las dimensiones de la imagen ampliada.

Ox y Oy indican el ancho y el alto de la porción del original que tratamos de reproducir. Sumados
con Xcopia e Ycopia no pueden exceder el tamaño de la imagen original.

Con estos parámetros la función 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 transformación de la copia de la original
¡Cuidado!

Observa que las imágenes en formato png se visualizan con deficiencias en los bordes de las áreas
transparentes.

Con el método que vemos a continuación ese problema se reduce considerablemente.

Lectura y redimensionado de imágenes externas

<?php
/* indicamos la ruta de la imagen original */
$original=$_SERVER['DOCUMENT_ROOT']."/php/images/caballos.jpg";
/* determinamos el formato de esa imagen */
for($i=strlen($original)-1;$i>0;$i--){
if (substr($original,$i,1)=="."){
$tipo=substr($original,$i+1);
break;
}
}
/* determinamos las dimesiones de la imagen original */
$tamano=getimagesize($original);
$orig_Ancho = $tamano[0];
$orig_Alto =$tamano[1];
/* vamos a tratar de obtener una imagen deformada para ello usaremos factores de
ampliación
distintos para para cada uno de los lados. Multiplicaremos por 2 el ancho y por
1.5 el alto */
$ampliacion_X=2;
$ampliacion_Y=1.5;
/* Pretendemos que la imagen resultante no tenga márgenes en blanco por tanto sus
dimensiones
van a ser las del original multiplicado por los factores de ampliacion */

Pág. 228
$resultado_Ancho=$orig_Ancho*$ampliacion_X;
$resultado_Alto= $orig_Alto*$ampliacion_Y;
/* creamos una copia de la imagen original. Debemos elegir la funcion adecuada al
tipo de aquella*/
switch($tipo){
case "jpg":
$copia=imagecreatefromjpeg($original);
break;
case "png":
$copia=imagecreatefrompng($original);
break;
case "gif":
$copia=imagecreatefromgif($original);
break;
}
/* insertamos la cabecera de nuestra imagen final ampliada */
Header("Content-type:image/jpeg");
/* creamos una imagen nueva en color verdadero*/
$ampliada=imagecreatetruecolor($resultado_Ancho,$resultado_Alto);
/* aplicamos un color de fondo a la nueva imagen para poder visualizar que
incluye
la transparencia del png y/o del gif */
if($tipo=="png" OR $tipo=="gif"){
$fondo=imagecolorAllocate($ampliada,255,255,200);
imagefill($ampliada,0,0,$fondo);
}
/* incrustamos la imagen importada sobre la que acabamos de crear teniendo en
cuenta
los parámetros de la función. 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 extensión de la imagen
original para elegir la función imagecreatefrom.... En el Header hemos puesto image/jpeg y, como es obvio, hemos
utilizado la función asociada a este formato (imagejpeg). Si sustituimos ambos valores por los correspondientes a otro
formato (gif, png) obtendríamos resultados similares.

Recortar y encuadrar imágenes externas

<?php
/* indicamos la ruta de la imagen original */
$original=$_SERVER['DOCUMENT_ROOT']."/php/images/aviones4.jpg";
/* determinamos el formato de esa imagen */
for($i=strlen($original)-1;$i>0;$i--){
if (substr($original,$i,1)=="."){
$tipo=substr($original,$i+1);
break;
}
}
/* determinamos el tamaño de la imagen original */
Pág. 229
$tamano=getimagesize($original);
$orig_Ancho = $tamano[0];
$orig_Alto =$tamano[1];
/* asignamos a una variable el margen en blanco de la imagen igual por los cuatro
lados */
$margen=15;
/* establecemos los recortes para reencuadrar la imagen original */
$recorte_izq=50; $recorte_sup=80; $recorte_der=40; $recorte_inf=60;
/* calculamos las dimensiones para utilizar como parámetros en la funcion
imagecopyresampled
ancho y alto de la imagen original después del recorte de encuadre */
$Ancho_recortado=$orig_Ancho-$recorte_izq-$recorte_der;
$Alto_recortado=$orig_Alto-$recorte_sup-$recorte_inf;
/* establecemos factores de ampliación iguales para evitar distorsiones */
$ampliacion_X=1.3; $ampliacion_Y=1.3;
/* determinamos las dimensiones de la imagen final teniendo en cuenta los
margenes y los factores de ampliación */
$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 márgenes al tamaño 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 visualizarán los
márgenes*/
$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 imágenes original y


resultante

Pág. 230
Ficheros MariaDB y/o MySQL

Los servidores de bases de datos MariaDB y MySQL

Una de las opciones más 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(acrónimo de Structured Query Language, es decir, Lenguaje estructurado de consultas) que hasta el
momento ha sido contemplado como un estandar para gestión de bases de datos. Falta por ver cual será la evolución
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 evolución 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 diseñado para convertirse en el centro de la industria de la base de datos de código abierto.

¡Cuidado!

Todos los ejemplos que incluimos aquí funcionan sin necesidad de hacer ninguna modificación en
servidores de bases de datos MariaDB.

Bases de datos y tablas

Si es este tu primer contacto con el mundo de las bases de datos, quizá sea importante conocer su argot ya que
en adelante tendremos que referirnos a tablas, campos, registros e índices y quizá no esté de más repasar un poco
esas ideas.

Pensemos en la base de datos como un armario archivador –directorio– que alberga una serie de cajones –
tablas– en los que se permite almacenar únicamente documentos de idéntico tipo –registros–. Imaginemos, por poner
dos ejemplos, que las solicitudes de matrícula de un centro tienen un formato unificado y se guardan mismo cajón y que,
con idéntico criterio, se haga lo mismo con los expedientes de los profesores .

Cada uno de los hipotéticos formularios de los supuestos anteriores tendría las mismas casillas –campos–, con
la única diferencia de que los datos contenidos en esos campos –de igual forma, dimensión y tamaño en todos
los registros– serían lo único que diferenciaría realmente las solicitudes de matrícula de dos alumnos.

Una oficina bien organizada no se conformaría con esto. A medida que crezca el número de solicitudes de los
alumnos irán surgiendo las dificultades para localizar un registro (la ficha de un alumno). Sería una excelente idea
organizar el archivo de tal forma que esa localización resulte lo más fácil y rápida posible. Una clasificación alfabética –
índice alfabético– o por fecha de nacimiento –otro índice– podría facilitar sustancialmente las cosas. Las bases de datos
MySQL disponen de todos esos rescursos.

Cuando hemos instalado MySQL en el directorio C:/ServidoresLocales/mysql y durante el proceso de instalación


se creó un subdirectorio llamado data (C:/ServidoresLocales/mysql/data) destinado a albergar todas las bases de datos de
nuestro servidor. En el caso de Ubuntu ese directorio es /var/lib/mysql. Cada una de las bases de datos que albergue el
servidor estará contenida en un subdirectorio cuyo nombre coincide con el de la propia base de datos.

Tanto en el caso de Windows como en el de Ubuntu, el instalador crea una base de datos llamada mysql y, por
tanto un subdirectorio para contenerla. En Windows será C:/ServidoresLocales/mysql/data/mysql mientras que en Ubuntu
se trata de /var/lib/mysql/mysql.

Si visualizamos los contenidos de ese subdirectorio podremos ver que mysql contiene una serie de ficheros en
los que un mismo nombre se repite con tres extensiones diferentes: .frm, .MYD y .MYI.

El directorio C:/ServidoresLocales/data

Pág. 231
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 extensión .frm contienen la estructura de una tabla. Es en alguna medida una especie
de formulario en blanco oformulario tipo. Los ficheros que tienen extensión MYD contiene los datos y aquellos que
acaban .MYI contienen los índices de cada tabla que cumplen una función idéntica a los índices de los libros. Por medio
de ellos resulta mucho más rápido encontrar una determinada información y al igual que ocurre con los libros –índice
general, onomástico, etcétera– pueden ser varios y de tipos distintos.

La base de datos mysql –creada durante la instalación– incluye una serie de tablas necesarias para la gestión del
servidor. Una de ellas (puedes verla en la imagen) es la tabla user –la más importante para nuestros fines– que contiene
información relativa a los usuarios del servidor de base de datos tales como: permisos y restricciones de acceso, nombres
usuarios, contraseñas, etcétera.

¡Cuidado!

El uso de los tres ficheros anteriores, es condición de las tablas tipo MyISAM .Otros tipos, que veremos en
temas posteriores, tales como InnoDB almacenan la información con una estructura diferente.

¿Cómo empezar con las bases de datos?

Igual que en el caso del ejemplo de la secretaría, lo razonable será empezar creando nuestros armarios –bases
de datos– para que posteriormente podamos ir diseñando los documentos –los campos y la estructura– de cada uno de
los tipos de impreso (tablas) que vayamos a manejar.

En nuestros ejemplos nos referiremo siempre a una base de datos –a la que llamaremos ejemplos– y un usuario
de nombre pepe con contraseña pepa que coinciden con el usuario creado por nuestro autoinstalador y por el referido en
los procesos de instalación autónoma y configuración tanto del servidor MariaDB como de MySQL.

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 Windows puedes ver aquí la forma de gestionarlo.

Una vez activos el servidor MySQL y Apache ya podemos utilizar phpMyAdmin. Lo habíamos instalado en un
subdirectorio de htdocs llamado phpmyadmin. Así que accedamos a través de la
dirección: http://localhost/phpmyadmin/ y se nos abrirá una página como la que sigue:
Pág. 232
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 contraseña han sido creados
automáticamente durante la instalación. El cuarto de ellos –el usuario pepe– es el que hemos creado durante el proceso
de instalación

Esta configuración es insegura ya que con los nombres de usuario por defecto –root– y sin contraseña cualquiera
podría acceder y manipular las bases de datos. Más adelante podremos borrar esos usuarios pero, por el momento,
dejémoslos así y añadamos un nuevo usuario.

Si pulsamos la opción editar (el icono en forma de lápiz que hay a la derecha de la casilla de verificación del
usuario sin nombre se nos abrirá una página como esta:.

Pág. 233
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 función PASSWORD para el campo del mismo nombre.

Una vez realizado el proceso anterior deberá quedarnos como aparece en la imagen. Pulsaremos en el
botón Continúe que hay al final de la página 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 contraseña
aparece encriptado como consecuencia de haber aplicado la función PASSWORD para garantizar la privacidad del
usuario. MySQL requiere esta encriptación.

Respecto a los YES, la explicación 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 gestión al
usuario pepe.

Creación de un fichero INCLUDE

En los scripts PHP, con los que manejemos las bases de datos, vamos a necesitar insertar continuamente: nombre
del servidor, nombre de usuario y contraseña.

Tanto la comodidad como la privacidad que hemos mencionado en páginas anteriores aconsejan guardar los datos
de usuario en lugar seguro. Así pues lo aconsejable será crear un fichero –llamémosle mysql.inc.php– idéntico al que
tenemos aquí debajo,(podemos copiar y pegar) y que podríamos guardar en un directorio seguro tal como
habíamos comentado aquí.

<?php
$mysql_server="localhost";
$mysql_login="pepe";
$mysql_pass="pepa";
?>

Pág. 234
Campos y conexiones

Conexión con el servidor de bases de datos

Antes de empezar a trabajar con bases de datos es imprescindible que ambos servidores –Apache y MySQL–
estén activos. Como paso inicial hemos de interconexionar ambos servidores de forma que sea posible tranferir
información de uno a otro. Para ello es necesario utilizar siempre una función PHP con la siguiente sintaxis:

$conexion=mysql_connect(servidor, usuario, contraseña)

donde $conexion es la variable que recoge el identificador del enlace, servidor es la dirección 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 contraseña la contraseña (en nuestro caso "pepa" ó "") . Estos tres valores –cadenas de
texto– deben ir escritos entre comillas.

Para cerrar la conexión utilizaremos la función:

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 código fuente de un script que realiza la apertura de una conexión y después la cierra y desde
aquí puedes comprobar su funcionamiento.

Si realizáramos una segunda conexión (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 conexión es utilizar los valores registrados en el fichero mysql.inc.php –lo hemos creado
en la página 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 ubicación, la ruta completa hasta el fichero en el que hemos guardado las claves de
conexión y para el que te hemos sugerido el nombre de mysql.inc.php.

En este supuesto como valores de los parámetros servidor, usuario y contraseña pondremos los nombres de las
variables:$mysql_server, $mysql_login y $mysql_pass sin encerrarlas entre comillas. Aquí tienes el código de un script que
realiza la apertura de una conexión y después la cierra y desde este enlace puedes comprobar el funcionamiento de esta
sintaxis alternativa.

La instrucción OR DIE

Es esta una buena ocasión para hablar de una instrucción PHP que no hemos mencionado hasta el momento. Se
trata de una opción alternativa a exit() que, como acabamos de ver en un ejemplo, interrumpe la ejecución de un script en
el momento de ser ejecutada.

Cuando se produce un error en la ejecución de un script –no poder establecer conexión con MySQL, por ejemplo–
no tiene sentido seguir ejecutándolo. Lo razonable será interrumpir el proceso y advertir del error. Si añadimos or die
('mensaje') a la instrucción$conexion=mysql_conect('servidor','usuario','contraseña') (sin paréntesis, ni comas, ni punto y
coma, sólo separado por un espacio) y ponemos el punto y coma de fin de instrucción después de cerrar este último
paréntesis

$conexion=mysql_conect('servidor','usuario','contraseña') or die ('mensaje')

en el caso de que se produzca un error se interrumpirá la ejecución del script y aparecerá en la ventana del
navegador el texto incluido en mensaje. Este es el código fuente de un script que produce un error –la contraseña es

Pág. 235
incorrecta– y que utiliza esta nueva sintaxis. Pero si lo ejecutas verás que aparece un mensaje de error generado por
PHP.

Este tipo de mensajes pueden deshabilitarse de la forma descrita aquí. Pero hay una técnica mucho más fácil.
Bastará con insertar delante de la función una arroba (@) para evitar que aparezcan. En este otro script lo hemos
incorporado y puedes comprobarlo aqui.

Información sobre bases de datos existentes

Antes de crear y/o borrar una base de datos puede ser conveniente y útil comprobar si ya existe. PHP dispone
de herramientas para conocer el número de bases de datos existentes en el servidor, así como sus nombres.Como es
lógico siempre necesitaremos tener establecida una conexión con el servidor de bases de datos.

$identificador=mysql_list_dbs($conexion)

dónde la variable $identificacor es un nuevo identificador imprescindible y previo a la determinación del número
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 número de bases de datos existentes en el servidor y utiliza como parámetro
($identificador) el resultado obtenido mediante la función anterior.

mysql_db_name($identificador, indice)

devuelve el nombre de la bases de datos identificada por el número indice que debe pertenecer al intervalo [0,$n).
Fíjate que i tiene que ser i<$n porque si, por ejemplo, $n=5 los cinco valores posibles de i serían: 0,1,2,3 y 4.

Una lista completa de todas las bases de datos existentes en el servidor podría hacerse mediante el siguiente
proceso:

 – Abrir la conexión.
 – Invocar a mysql_list_dbs.
 – Contar el número 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 código fuente de un ejemplo completo y desde aquí puedes ejecutarlo

Crear una base de datos

La creación de una base de datos también requiere una conexión previa y utiliza la siguiente sintaxis:

mysql_query ("CREATE DATABASE nombre")


O
mysql_query ("CREATE DATABASE IF NOT EXISTSnombre")

dónde nombre es el nombre de la nueva base de datos. Esta función 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 función
nos devolverá FALSE. Aquí tienes el código de un ejemplo de creación de una base de datos. Si lo ejecutas dos
veces podrás comprobar que en la segunda oportunidad te aparece el mensaje diciendo que no ha sido posible crearla.

Pág. 236
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 opción, en caso de que ya existiera
no produce ningún mensaje de error.

Borrar una base de datos

Para borrar una base de datos se requiere el uso de la siguiente función PHP:

mysql_query ("DROP DATABASE nombre")

donde nombre es el nombre de la base de datos y debiendo ponerse toda la cadena del paréntesis entre comillas.
Esta función devuelve TRUE cuando se ejecuta con éxito, y FALSE en el caso contrario. Este es el código de
un script que puede borrar la base creada anteriormente. Igual que ocurría al tratar de crearla, si intentamos borrar una
base de datos inexistente nos devolverá FALSE.

Automatizar la conexión

Con nuestros conocimientos sobre PHP ya estamos en condiciones de hacer más cómoda la conexión. Creemos
una función que realice de forma automática la conexión con MySQL y guardémosla 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 ningún valor


# para que pueda recoger el identificador de conexión
# una vez que se haya establecido esta

$c;
# escribamos la función que hace la conexión
# como pretendemos que el valor del identificador
# sea usado fuera de la función, 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>Conexión establecida<br>";
}else{
print "<br>No ha podido realizarse la conexión<br>";
# el exit lo incluimos para que deje de ejecutarse
# el script si no se establece la conexión
exit();
}
}

# esta función asignará a $c el valor del identificador

# repetimos la misma función con otro nombre


# ahora quitaremos el mensaje de conexión establecida
# consideraremos que si no hay mensaje se ha establecido
# asi quedará limpia nuestra página

function conecta2(&$c){
global $mysql_server, $mysql_login, $mysql_pass;

Pág. 237
if($c=mysql_connect($mysql_server,$mysql_login,$mysql_pass)){
}else{
print "<br>No ha podido realizarse la conexión<br>";
exit();
}
}
?>

Si sustituyes el contenido de tu mysql.inc.php por el que tienes aquí arriba –puedes eliminar la líneas de
comentario al hacerlo– estaremos en disposición de ejecutar scripts como este.

Estos ejemplos utilizan cada una de las dos funciones.

Ver código fuente Ver código fuente

Depurando los procesos de creación y borrado de bases de datos

Cuando intentamos crear una base de datos ya existente o borrar una inexistente las funciones mysql_query nos
devuelven FALSE pero esa respuesta no nos dice la causa por la que no ha sido posible la ejecución de la instrucción.

Sería mucho más interesante comprobar la existencia o inexistencia de una base de datos antes de ejecutar
esas instrucciones y que después de la comprobación se nos presentara un mensaje informativo. MySQL dispone de una
sentencia para este fin, pero –aunque la vamos ver más adelante– olvidémosnos de su existencia e intentemos crear
nuestro propio script de comprobación.

Combinando las instrucciones anteriores no resulta difícil hacerlo. Aquí tienes un ejemplo de código para efectuar
esa comprobación alcrear una base de datos y este otro código es para el caso de borrado.

Puedes experimentar con estos scripts, sustituirlos por otros propios en los que utilices tus propias funciones.
Nada es absoluto.

Las bases de datos de nuestros ejemplos

En las páginas siguientes vas encontrarte con una serie de ejemplos. Por razones obvias no vamos a incluir aquí
el acceso a los scripts que permiten la creación, modificación y borrado de tablas. Lo que si haremos será incluir enlaces
que permitan visualizar el código fuente utilizado en esos procesos. Aquí tienes el script mediante el se crea la base de
datos que utilizaremos en nuestros ejemplos.

Código fuente creación de


base de datos
este otro código Pulsa en este enlace para que cree automáticamente la base de datos que va a contener los sucesivos
ejemplos que hemos incluido en estos materiales.

Pasos previos a la creación de tablas

Conocidos los procesos de creación, listado y borrado de bases de datos ya estamos en disposición en empezar
a tratar lo relativo a las tablas. Es muy necesario conocer los diferentes tipos de campos que pueden contener
las tablas de MySQL. Saber las posibilidades que ofrece cada uno de ellos será fundamental a la hora de diseñar una
tabla. En ese momento tendremos que decidir qué campos son necesarios, cuál es tipo requerido, cuáles han de ser sus
dimensiones y también cuáles de ellos requerirán ser tratados como índices.

Tipos de campo bien elegidos y un tamaño adecuado a las necesidades reales de nuestro proyecto son las mejores
garantías para optimizar el tamaño de la tabla y para hacerla realmente eficaz. El grado de eficiencia de una base de
datos suele ser directamenteproporcional al tiempo invertido en el análisis de la estructura de sus tablas.

Tipos campos en MySQL

MySQL tiene habilitados diversos tipos de campos que en una primera aproximación podrían clasificarse en tres
grupos:

Pág. 238
 Campos numéricos
 Campos de fecha
 Campos de cadenas de caracteres

Campos numéricos

MySQL soporta los tipos numéricos exactos (INTEGER, NUMERIC, DECIMAL, y SMALLINT) y los tipos
numéricos aproximados(FLOAT, DOUBLE precision y REAL). Los campos que contienen números enteros admiten el
parámetro UNSIGNED, que implica que no admita signos, por lo que solo aceptaría enteros positivos. Todos los
campos numéricos admiten el parámetro ZEROFILL cuya función es completar el campo con ceros a la izquierda hasta
su longitud máxima.

Tipos de campos numéricos enteros

Estos son los distintos tipos de campos numéricos enteros que admite MySQL. Los parámetros señalados entre
corchetes son opcionales.

TINYINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero muy pequeño. Con la opción UNSIGNED puede tomar valores entre 0 y 255. En caso contrario, puede estar comprendido entre -
128 y 127.
El parámetro ZEROFILL sólo tiene sentido junto con la opción UNSIGNED ya que no es habitual rellenar los números negativos con ceros a la
izquierda del signo.
El valor por defecto de parámetro M (número de cifras) es 4 si no está activada la opción UNSIGNED. Si esta opción estuviera activada el valor
por defecto sería M=3. Para valores de M >valor por defecto reajusta el tamaño al valor por defecto.
Si se asigna a M un valor menor que cuatro limita el número de caracteres al tamaño especificado considerando el signo sólo en los números
negativos.
Por ejemplo, si M=3 admitiría 148, pero si intentamos insertar -148 recortaría por la izquierda y solo insertaría -14.
Si intentamos insertar un valor fuera de rango registraría el valor dentro del rango más próximo a él.
P. ej.: Si tratamos de insertar el valor 437 escribiría 127 ó 255, este último en el caso de tener la opción UNSIGNED.
Si pretendiéramos insertar -837 con la opción UNSIGNED escribiría 0 y sin ella pondría -128.
El tamaño de un campo TINYINT es de 1 byte.

SMALLINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero pequeño. Con la opción UNSIGNED puede tomar valores entre 0 y 65 535. En caso contrario, puede estar comprendido entre -
32 768 y 32 767.
Son válidos los comentarios hechos para TINYINT, excepto los relativos a los valores por defecto de M que en este caso serían 6 ó 5. Su
tamaño es de 2 bytes.

MEDIUMINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero mediano. Con la opción UNSIGNED puede tomar valores entre 0 y 16 777 215. En caso contrario, puede estar comprendido
entre -8 388 608 y 8 388 607.
También son válidos los comentarios hechos para TINYINT, excepto los relativos al valor por defecto de M que en este caso serían 8. Su
tamaño es de 3 bytes.

INT [(M)] [UNSIGNED] [ZEROFILL]

Número entero. Con la opción UNSIGNED puede tomar valores entre 0 y 4 294 967 295. En caso contrario, puede estar comprendido entre -2
147 483 648 y 2 147 483 647.
Son válidos todos los comentarios de los casos anteriores. Su tamaño es de 4 bytes.

INTEGER [(M)] [UNSIGNED] [ZEROFILL]

Es un sinónimo de INT

BIGINT [(M)] [UNSIGNED] [ZEROFILL]

Número entero grande. Con la opción UNSIGNED puede tomar valores entre 0 y 18 446 744 073 709 551 615. En caso contrario, puede estar
comprendido entre -9 223 372 036 854 775 808 y 21 474 839 223 372 036 854 775 807 647, pero al usarlo desde PHP estará sujeto a las
limitaciones máximas de los valores numéricos de este.
Son válidos todos los comentarios de los casos anteriores. Su tamaño es de 8 bytes.

Números de coma flotante


Pág. 239
Por la estructura binaria de los microprocesadores y habida cuenta de que algunos números no enteros –sin ir
más lejos, el 0.1– requerirían infinitos caracteres binarios para su representación exacta, se hace necesario introducir
un redondeo en su tratamiento informático y como consecuencia de ello asumir que se generan errores de medida.

Esta circunstancia obligó al tratamiento de los números decimales mediante el llamado Standar de Aritmética de
Punto Flotante, un algoritmo definido por la IEEE (Institute of Electrical and Electronics Engineers) que unificó los
procesos de representación de números en ordenadores con lo que son uniformemente controlables los errores
introducidos.

El Standar de Aritmética de Punto Flotante estableció dos niveles de precisión:

 Precisión Simple, en la que todo número debe ser almacenado en 32 bits (4 bytes).
 Doble precisión, en la que los números se almacenan en 64 bits (8 bytes).

Campos númericos de coma flotante

Estos son los distintos tipos de campos numéricos de coma flotante que admite MySQL. Los parámetros señalados
entre corchetes son opcionales.

FLOAT(x) [ZEROFILL]

Número de coma flotante. Ignora la opción UNSIGNED, pero sí acepta ZEROFILL, por lo que debe prestarse atención a estas opciones ya que
no sería demasiado habitual una presentación como esta: 000-3.47
El valor de x especifica la precisión. Si x<=24 será de precisión simple. cuando 24 <x <=53 lo convertirá automáticamente a doble precisión.
Cuando no se especifica el valor de x considera el campo como de precisión simple. Su tamaño es de 4 bytes si x<=24 y de 8 bytes cuando 24
<x <=53

FLOAT [(M,D)] [ZEROFILL]

Número de coma flotante de precisión simple. Son válidos los comentarios relativos a las opciones UNSIGNED y ZEROFILL del caso anterior.
Toma valores en los intervalos siguientes:
 -3.402823466E+38 a -1.175494351E-38
 0y
 1.175494351E-38 a 3.402823466E+38.
M es la anchura máxima de visualización y D es el número de decimales. Si M > 24 se convierte automaticamente a doble precisión
FLOAT sin argumentos representa un número de coma flotante y precisión simple.

DOUBLE [(M,D)] [ZEROFILL]

Número de coma flotante de doble precisión. Siguen siendo válidos los comentarios relativos a las opciones UNSIGNED y ZEROFILL del
caso anterior.
Toma valores en los intervalos siguientes:
 -1.7976931348623157E+308 a -2.2250738585072014E-308
 0y
 2.2250738585072014E-308 a 1.7976931348623157E+308
M es la anchura máxima de visualización y D es el número de decimales.
DOUBLE sin argumentos representa un número de coma flotante y precisión doble.

REAL [(M,D)] [ZEROFILL]

Es sinónimo de DOUBLE.

DECIMAL [(M[,D])] [ZEROFILL]

Es un número de coma flotante y doble precisión que se almacena como un campo de tipo CHAR.
El valor es guardado como una cadena donde cada carácter representa una cifra. La coma y el signo menos de los números negativos no son
tenidos en cuenta en el valor de M -anchura máxima de visualización- aunque si se reserva -automáticamente- espacio para ellos en campo.
Si D vale 0 no tendrá parte decimal. Los números toman valores en el mismo intervalo especificado para DOUBLE.
Los valores por defecto de M y D son respectivamente 10 y 0.
Ocupan M+2 bytes si D > 0; M+1 bytes si D = 0 ó D+2 bytes si M < D

NUMERIC(M,D) [ZEROFILL]

Pág. 240
Se comporta de forma idéntica a DECIMAL

Campos de fecha

MySQL dispone de campos específicos 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 (año-mes-día) .
Su tamaño es de 3 bytes.

DATETIME

Recoge una combinación de fecha y hora dentro del intervalo 00:00:00 del día 01-01-1000 y las23:59:59 del día 31-12-9999. MySQL guarda
los valores DATETIME con formato AAAA-MM-DD HH:MM:SS (año-mes-día hora:minutos:segundos) . Su tamaño 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 tamaño es de 3 bytes.

YEAR 0 YEAR(2) o YEAR(4)

Recoge un año en formato de cuatro cifras (YEAR o YEAR(4)) o en formato de dos cifras (YEAR(2))dentro del intervalo 1901 a 2155 en el caso
de cuatro cifras o de1970 a 2069 si se trata de dos cifras. Su tamaño es de 1 byte.

TIMESTAMP [(M)]

Recoge un tiempo UNIX. El intervalo válido va desde 01-01-1970 00:00:00 a cualquier fecha del año 2037.
El parámetro 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 opción NUL guardará la hora actual. Cuando se asigna 8 o 14 como parámetros es considerado como un número y para las
demás opciones comouna cadena.
Independientemente del valor del parámetro, un campo TIMESTAMP siempre ocupa 4 bytes.

Campos tipo cadena de caracteres

MySQL dispone de campos específicos para el almacenamiento de datos alfanuméricos. Son los siguientes:

CHAR (M) [BINARY]

Es una cadena de tamaño fijo que se completa a la derecha por espacios si es necesario.
El parámetro M puede valer de 1 a 255 caracteres.
Los espacios finales son suprimidos cuando la cadena es insertada en el registro.
Los valores de tipo CHAR son elegidos y comparados sin tener en cuenta Mayúsculas / Minúsculas y utilizan el juego de carácteres por
defecto.
Se puede utilizar el operador BINARY para hacer la cadena sensible a Mayúsculas / Minúsculas.
Se puede utilizar un campo tipo CHAR(0) con el atributo NULL para almacenar una valor booleano. En este caso ocupará un solo byte y podrá
tener únicamente dos valores: NUL ó "".
Su tamaño es de M bytes siendo 1 <= M <= 255 .

VARCHAR(M) [BINARY]

Es una cadena de caracteres de longitud variable. Su tamaño máximo -especificado en el parámetro M- puede estar comprendido
entre 1 y 255 caracteres. Con la opción BINARY es capaz de discriminar entre Mayúsculas / minúsculas.

TINYBLOB o TINYTEXT

TINYBLOB y TINYTEXT son cadenas de caracteres de longitud variable con un tamaño máximo de 255 (28 - 1) caracteres.
La diferencia entre ambas es que TINYBLOB discrimina entre Mayúsculas / minúsculas, 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.

Pág. 241
Si se intenta guardar en un campo de este tipo una cadena de mayor longitud que la especificada solamente se guardarán los M primeros
caracteres de la cadena.

BLOB o TEXT

BLOB y TEXT son cadenas de caracteres de longitud variable con un tamaño máximo de 65535 (216 - 1) caracteres.
La diferencia entre ambas es que BLOB si discrimina entre Mayúsculas / minúsculas, 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 máxima de 16.777.215 (224 - 1)
caracteres.
Son válidas las especificaciones hechas en el apartado anterior.
El tamaño máximo de los campos de este tipo está sujeto a limitaciones externas tales como la memoria disponible y el tamaño del buffer de
comunicación servidor/cliente.

LONGBLOB o LONGTEXT

Su única diferencia con la anterior es el tamaño máximo de la cadena, que en este caso es 4.294.967.295 (2 32 - 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 insertaría una cadena vacía.

SET('valor1','valor2','valor3'...)

Es una cadena de caracteres formados por la unión de ninguno, uno o varios de los valores de una lista. El máximo de elementos es 64.
Los valores que deben escribirse en los campos de este tipo han de ser numéricos, 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 añadir un registro serían
los siguientes.

Incluir valores Código valor Cadena Equiv.


val1 val2 val3 val1 val2 val3 binaria decimal
Si Sí Sí 1 1 1 111 7
Si Sí No 1 1 0 011 3
Si No Sí 1 0 1 101 5
No Sí Sí 0 1 1 110 6
No No Sí 0 0 1 100 4
No Sí NO 0 1 0 010 2
Si No No 1 0 0 001 1
No No No 0 0 0 000 0

Pág. 242
Creación de tablas

Tipos de tablas

MySQL permite usar diferentes tipos de tablas tales como: ISAM, MyISAM o InnoDB.

Las tablas ISAM (Indexed Sequential Access Method) son las de formato más antiguo. Están limitadas a tamaños
que no superen los 4 gigas y no permite copiar tablas entre máquinas con distinto sistema operativo.

Las tablas MyISAM son el resultado de la evolución de las anteriores adaptadas por MySQL durante mucho tiempo
como el formato por defecto para sus servidores de bases de datos. En las versiones más 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 compañía finlandesa InnoBase a la que deben su nombre) tienen
una estructura distinta a la de MyISAM, ya que utilizan un sólo 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 más adelante de ello.

La definición de uno u otro formato (MyISAM o InnoDB) debe hacerse en el momento de la creación de tabla y
solo reguiere agregarType=MyISAM ó Type=InnoDB a la sentencia MySQL encargada de crearla.

Creación de tablas

Las tablas son elementos de las base de datos. Por esa razón nos resultará imposible crear una tabla sin
tener creada y seleccionadauna base de datos. Es por eso que para la creación de una tabla se necesitan los siguientes
requisitos:

 – Tener abierta una conexión con el servidor MySQL.


 – Tener seleccionada una base de datos.

Conexión con el servidor

La hemos comentado en la página anterior. Recuerda que requería la función: $conexion = mysql_connect (
servidor, usuario, contraseña ) y que esa conexión ha de ser establecida antes de cualquier otra intervención relacionada
con accesos a bases de datos y tablas.

Selección de la base de datos

Dado que podemos manejar bases de datos distintas –en estos materiales usaremos ejemplos y practicas– es
preciso decir a MySQL con qué base queremos trabajar.

mysql_select_db(nombre_base_datos, $conexion)

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
llevaría comillas. El segundo parámetro$conexion es el identificador de conexión. Es decir, la variable creada al establecer
la conexión con MySQL. Este valor debe insertarse siempre. La razón es que MySQL permite mantener abiertas varias,
de forma simultánea, varias conexiones (podríamos manejar más de un servidor de bases de datos) y en esas condiciones
no pueden darse ambigüedades respecto a la base que pretendemos usar.

Creación de una tabla

En todas las transacciones PHP – MySQL habremos de utilizar instrucciones de ambos lenguajes. La forma
habitual –hay algunas excepciones– en la que PHP se comunica con MySQL es por medio de la función genérica:

mysql_query("sentencia", $conexion);

Pág. 243
donde la cadena sentencia contiene las instrucciones propias de MySQL y $conexion sigue siendo la variable que
contiene el identificador de conexión.

La creación 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, dónde campo1, campo2,
etc. son las definiciones de los campos que pretendemos que contenga la tabla y tipo puede ser MyISAM o InnoDB según
el tipo de tabla que queramos crear.

La única diferencia entre ambas opciones es que la segunda daría un error si tratáramos de crear una tabla
preexistente (deberíamos recurrir al procedimiento que hemos visto cuando creábamos bases de datos) mientras que la
primera no da ese mensaje de error.

Definición de campos en una tabla MySQL

Cada uno de los campos que vayamos a crear en una tabla requiere una definición que debe contener lo siguiente:

– nombre del campo

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, etcétera. No va entre comillas nunca y
MySQL diferencia mayúsculas/minúsculas.

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 más aconsejable es evitar esta situación.

– tipo y dimensiones

Los tipos de campos –los hemos visto en las páginas anteriores– tienen que ajustarse a uno de los soportados
por MYSQL. El tipo de campo se escribe a continuación del nombre sin otra separación que un espacio y requieren
la sintaxis –estricta– correspondiente a cada tipo.

Cuando se establezca una dimensión como parámetro opcional de un campo deben tenerse en cuenta algunos
detalles:

 – Su valor se escribe entre paréntesis y se incluye después del nombre del campo.
 – Si en un campo numérico introdujéramos valores que exceden los límites, su valor no se registraría en la tabla sino el
valor del límite más próximo correspondiente a ese tipo de campo.
 – Supongamos un campo tipo TINYINT que permite valores comprendidos entre -128 y 127. Si asignáramos en uno de
sus registros un valor igual a 234 se escribiría en la tabla 127 (el límite superior) y si ponemos -834 escribiría el límite
inferior, es decir, -128.
 – En caso de cadenas, si el valor introducido sobrepasara la longitud máxima permitida, la cadena sería recortada y
únicamente se registraría el número máximo 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 después del nombre del
campo o de la dimesión (en los casos en que se incluya).

Ejemplo de creación de una tabla

Pág. 244
<?php
/* nos conectamos con el servidor
recogiendo en $c el identificador de conexión */
$c=mysql_connect ("localhost","pepe","pepa") or die ("Imposible conectar");
# seleccionamos una base de datos existente
# de lo contrario nos daría un error
# pondremos como nombre ejemplos nuestra base de datos
# creada en la página anterior y usaremos $c
# importante no olvidarlo
mysql_select_db ("ejemplos", $c);
/* ahora ya estamos en condiciones de crear la tabla
podríamos escribir ya la instrucción 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 añadiendo cosas */
# la primera parte de la instrucción es esta (espacio final incluido
$crear="CREATE TABLE IF NOT EXISTS ";
# añadiremos el nombre de la tabla que será ejemplo1
# fijate en el punto (concatenador de cadenas) que permite
# ir añadiendo a la cadena anterior
$crear .="ejemplo1 ";
#ahora pongamos el paréntesis (con un espacio delante)
#aunque el espacio también podría detrás de ejemplo1
$crear .="( ";
# insertemos el primer campo y llamemoslo num1
# hagamoslo de tipo TINYINT sin otras especificamos
# sabiendo que solo permitira valores numéricos
# comprendidos entre -128 y 127
$crear .="num1 TINYINT , ";
# LOS CAMPOS SE SEPARAN CON COMAS por eso
# la hemos incluido al final de la instrucción anterior

# ahora num2 del mismo tipo con dimensión 3 y el flag UNSIGNED


# Y ZEROFILL que: cambiará los límites de valores
# al intervalo 0 - 255, y rellenará con ceros por la izquierda
# en el caso de que el número 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 añadiremos un valor por defecto
# de manera que cuando se añadan registros a la tabla
# se escriba automaticamente ese valor 13 en el caso
# de que no le asignemos ninguno a ese campo
# por ser numérico 13 no va entre comillas
$crear .="num3 TINYINT (7) UNSIGNED ZEROFILL DEFAULT 13, ";
# ahora un número decimal num4 tipo REAL con 8 digitos en total
# de los cuales tres serán decimales y también rellenaremos con ceros
# Pondremos como valor por defecto 3.14
$crear .="num4 REAL (8,3) ZEROFILL DEFAULT 3.14, ";
# añadamos una fecha
$crear .="fecha DATE, ";
/* una cadena con un limite de 32 carácter 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 añadir el paréntesis conteniendo toda la instrucción
Pág. 245
$crear .=")Type=MyISAM";
/* tenemos completa la sentencia MYSQL
solo falta ejecutarla mediante mysql_query
ya que la conexión está abierta
y la base de datos ya está seleccionada */

/* pongamos un condicional de comprobación */


if(mysql_query($crear,$c)){
print "Se ha creado la base de datos<br>";
print "La sentencia MySQL podríamos haberla escrito asi:<br>";
print "mysql_query("."\"".$crear."\" , $c);";
}else{
print "Se ha producido un error al crear la tabla";
}
?>

Consideraciones sobre IF NOT EXISTS

Esta variante de CREATE –aplicable tanto en tablas como en bases de datos– tiene la ventaja de no dar mensajes
de error en caso de intentar crear una tabla –o base– ya existente, pero puede darnos algún sobresalto porque no
advierte que la tabla no ha sido creada y puede darnos la sensación de que puede haber reescrito una tabla anterior. Si
se ejecuta reiteradamente el script no aparece ningún mensaje de error.

Código fuente creación de


base de datos

Pág. 246

También podría gustarte