Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Hernán Beati
PHP
Creación de páginas Web dinámicas
Hernán Beati
Alfaomega
Beati, Hernán
PHP : creación de páginas Web dinámicas. - 1a. ed. - Buenos Aires : Alfaomega Grupo Editor Argentino,
2011.
400 p. ; 23x17 cm.
ISBN 978-987-1609-21-5
Queda prohibida la reproducción total o parcial de esta obra, su tratamiento informático y/o la transmisión por
cualquier otra forma o medio sin autorización escrita de Alfaomega Grupo Editor Argentino S.A.
Internet: http://www.alfaomega.com.mx
Todos los derechos reservados © 2011, por Alfaomega Grupo Editor Argentino S.A.
Paraguay 1307, PB, ofcina 11
NOTA IMPORTANTE: La información contenida en esta obra tiene un f n exclusivamente didáctico y, por lo tanto,
no está previsto su aprovechamiento a nivel profesional o industrial. Las indicaciones técnicas y programas
incluidos han sido elaborados con gran cuidado por el autor y reproducidos bajo estrictas normas de control.
Alfaomega Grupo Editor Argentino S.A. no será jurídicamente responsable por errores u omisiones, daños y per-
juicios que se pudieran atribuir al uso de la información comprendida en este libro, ni por la utilización indebida
que pudiera dársele.
Los nombres comerciales que aparecen en este libro son marcas registradas de sus propietarios y se mencio-
nan únicamente con fnes didácticos, por lo que Alfaomega Grupo Editor Argentino S.A. no asume ninguna re-
sponsabilidad por el uso que se dé a esta información, ya que no infringe ningún derecho de registro de marca.
Los datos de los ejemplos y pantallas son fcticios, a no ser que se especifque lo contrario.
Hernán Beati
Mensaje del Editor
No nací programador. Por esta razón, estoy convencido de que todas las perso-
nas pueden aprender a programar y me especializo en su capacitación.
Me formé pedagógicamente haciendo un magisterio de música hace veinte
años; luego me dediqué a la literatura, más tarde al diseño gráfco y, hacia fnes
del siglo XX, me convertí en diseñador Web.
Conocer el lenguaje PHP fue lo que me hizo estudiar Análisis de Sistemas, y
pronto pasé del diseño a la programación Web. Comencé a enseñar lo que
sabía: fundé el campus virtual de SaberWeb, y fui ayudante de cátedra en la
Universidad Maimónides, en la materia Programación Multimedial.
Tiempo después fui docente en los institutos ImageCampus y ITMaster. En la
Universidad Tecnológica Nacional dicté varios años el curso Professional Web-
master y fui el creador del curso de Programador Web Avanzado, que aún se
sigue dictando.
Sigo capacitándome continuamente: los últimos cursos que hice fueron sobre
UML y patrones de diseño de objetos, y realicé talleres de Usabilidad y de
Accesibilidad Web.
Siempre me gustó el modelo de desarrollo colaborativo, propio del software libre.
El complemento perfecto de las matrices Devolviendo datos a la salida con return .186
ordenadas y de los archivos de texto ..144 Las ventajas de evitar echo y print
El concepto de contador 145 desde dentro de las funciones 189
El concepto de acumulador 147 Alcance de las variables en las funciones:
Cómo recorrer una matriz con «foreach» ..148 locales y globales 191
Cómo repetir algo una cantidad
desconocida de veces: el «while» 150
CAPITULO 10
Las funciones «list» y «each» 151
Funciones incorporadas más usadas ...195
El bucle do-while 152
Funciones de manejo de caracteres 196
Condicionales dentro de bucles 153
Limpiar espacios en blanco 196
La técnica de la señal o “fag” 154
Función trim 196
Los archivos de texto 156
Función ltrim 197
Un contenedor simple y permanente,
para datos no muy confdenciales 156 Función rtrim o chop 197
1 . Modos de apertura de archivos 157 Comparar evitando errores: strtolower y
strtoupper 197
2. Operaciones posibles: lectura,
escritura, agregados de datos 158 Contar la cantidad de letras de un texto ..198
3. Cierre de un archivo 159 Obtener «partes» de una cadena
Formas de leer datos desde un archivo de caracteres 199
de texto 159 Función substr 199
Leer línea por línea con la función «fle» ...159 Función strpos 201
Función fpassthru 162 Función strstr 203
Función fread 163 Buscar algo en un texto con preg_match 204
Función fgetc 164 Buscar y reemplazar: str_replace 207
Función feof 165 Dividir o ensamblar un texto con
delimitadores: explode e implode 207
Función fgets 167
Convertir saltos de línea a breaks HTML ..209
Función fgetss 167
Funciones printf y sprintf 211
Cómo escribir y acumular datos
Funciones de fecha y hora 213
en un archivo de texto 169
El concepto de timestamp 213
Funciones fputs y fwrite 170
Obtener fecha y hora actual con la
Acumular datos sin borrar lo anterior 171 función time 213
Convirtiendo de timestamp a formatos
CAPITULO 9 más humanos 214
Creando y usando funciones 173 Otra forma de mostrar fechas y horas:
Planifcando nuestros sistemas Web 174 la función date 215
El modelo basado en la ejecución Zonas horarias 217
de tareas (funciones) 174
De día, mes y año, a valor de timestamp:
La función: una caja cerrada que procesa la función mktime 218
datos 176 Validar si una fecha es correcta con
Declarar una función 179 checkdate 219
Nuestra primera función 180 Funciones de envío de correos electrónicos ..220
Parámetros de entrada 182 Un servidor de correos en el hosting 220
Funciones con varios parámetros 184 Envío básico 220
Funciones sin parámetros 185 Casos prácticos 221
Para comodidad del lector, el código utilizado en el libro se encuentra disponible para ser
descargado desde:
http://www.alfaomega.com.mx/archivosadicionales
Alfaomega © ITMasterPROFESSIONAL TRAINING
i
1
MÁS ALLÁ
DE HTML Y CSS
Eso explica por qué se propaga con tanta velocidad el conocimiento de PHP entre dise-
ñadores y programadores de otros lenguajes. Es la clave para llevar a cabo cualquier proyecto
que trascienda las páginas Web HTML estáticas.
Y el detalle fundamental: con PHP, nuestros presupuestos pueden llegar a tener uno o
incluso dos ceros más que los presupuestos que hacíamos como diseñadores o programado-
res de otros lenguajes.
Además, PHP es fácil de aprender.
2. En ese momento, el navegador envía una petición que solicita esa página. Ese pedido
“viaja” desde nuestro navegador hasta la máquina hosting que hospeda el archivo reque-
rido. Pero el navegador no remite únicamente el pedido del archivo que necesita, sino que
lo acompaña con un número que nos identifca inequívocamente: nuestra dirección IP.
Figura 1-3. El servidor Web busca en el disco rígido del hosting el archivo solicitado.
El rol del servidor Web es similar al del empleado de la pizzería que atiende al
teléfono y va a buscar el pedido a la cocina de la pizzería.
4. Ese servidor Web, una vez que localizó el archivo solicitado, envía, entrega o “sirve”
(de ahí su nombre: “servidor”) el archivo al navegador que se había quedado esperan-
do una respuesta en la dirección IP que lo identifca.
Figura 1-4. El servidor Web envía el archivo solicitado a la dirección IP del navegador.
Equivaldría al viaje de la moto que nos trae la pizza hacia nuestra casa.
5. Una vez que llegó el archivo hasta nuestro navegador, éste se encarga de interpretar
los contenidos de ese archivo de texto y código HTML, armando cada elemento (textos,
tablas, colores) de la página recibida en nuestra pantalla para que la podamos leer.
3. Este programa intérprete de PHP busca en el disco rígido del hosting el archivo .php
que fue solicitado, y comienza a leer su código línea por línea, buscando determinadas
“marcas” o etiquetas que nosotros, como programadores, hemos dejado escritas y que
contienen órdenes destinadas a ese programa intérprete de PHP.
Figura 1-8. El intérprete de PHP busca las marcas con órdenes para él.
4. Cuando este programa intérprete de lenguaje PHP encuentra estas órdenes, las ejecuta
(las procesa) y, a continuación, reemplaza todas las órdenes que hubiera entre la apertu-
ra y el cierre de la etiqueta de PHP por el resultado de procesar esas órdenes. Es decir,
borra las órdenes del código HTML en el que estaban escritas y, en su lugar, coloca los
datos obtenidos como consecuencia de la ejecución de esas órdenes.
Figura 1-9. El intérprete de PHP borra cada orden y en su lugar escribe el resultado de procesar esa
orden.
6. En el código fuente que le llega al navegador, no vemos ningún rastro de la orden que
habíamos escrito para el software de PHP, ya que este software se ocupó de borrarla
para que nadie la vea, y en el lugar exacto en el que habíamos escrito esa orden, colocó
“el resultado de ejecutar esa orden”, es decir, la fecha, que se ocupó de conseguir.
En resumen, el pre-proceso de páginas PHP consiste en esta serie de pasos: dejamos
escritas entre medio de nuestras páginas algunas órdenes destinadas al software intérpre-
te de PHP (órdenes que casi siempre consisten en que el software de PHP obtenga cierta
información, como la fecha del ejemplo anterior); luego, colocamos otras órdenes para que
el software intérprete de PHP “realice algo” con esa información, típicamente, que la escriba
dentro del código fuente de la página HTML que se enviará al navegador del usuario.
En la fgura 1-10, observamos algunas órdenes en lenguaje PHP escritas en medio del
código HTML de una página:
Páginas estáticas
De la diferencia entre los procesos que sufren las páginas HTML comunes y las páginas PHP,
podemos concluir que las páginas Web, escritas únicamente en lenguaje HTML, son estáti-
cas: es decir, nunca cambian su contenido: pase lo que pase, lo que llegará al navegador
del usuario es lo que ha sido escrito en ellas por el diseñador Web, ni más ni menos, siempre
lo mismo.
Páginas dinámicas
Por el contrario, las páginas que incluyen código escrito en lenguaje PHP, nos dan la opor-
tunidad de personalizar su contenido sobre la base de ciertas órdenes escritas (como en el
ejemplo anterior de la fecha, la página hoy mostrará una fecha y mañana otra, y así sucesiva-
mente; es decir: siempre generará un contenido distinto, variable).
El contenido de esas páginas, al menos en partes de ellas, cambiará y no será siempre
el mismo, ya que dependerá de la información que obtenga el software de PHP y coloque en
ellas. Serán páginas dinámicas.
Figura 1-11. Esquema de interacción entre los programas que participan cuando las páginas
utilizan una base de datos.
Si pretendiéramos hacer este tipo de sitios únicamente con HTML, deberíamos crear
esta página manualmente y, en caso de alguna modifcación en los datos de alguno de los
productos (un nuevo producto, o quitar uno existente), deberíamos modifcar el archivo
HTML a mano, y volver a colocar en el hosting una copia actualizada de esta página HTML
mediante FTP. Así, en todos los cambios de cualquiera de los miles de artículos que se
muestran.
En cambio, con PHP y MySQL, podemos crear una base de datos que contenga
información sobre los miles de productos que se mostrarán. Luego, utilizaremos una pági-
na dinámica escrita en PHP, que incluya la orden de leer esa base de datos y publicar los
productos. Si modifcamos los datos, éstos se reemplazarán directamente en la base de
datos, sin necesidad de modifcar ni una línea de las páginas Web que exhiben los produc-
tos, ya que la orden sigue siendo exactamente la misma: “leer la base y mostrar todos los
productos”.
Otra vez, para grafcar la idea, la simplifcaremos, pero pronto lo aprenderemos a pro-
gramar para que funcione:
<p>
<?php
Atención, software de PHP!: Quiero que le pidas a la base de
datos la lista de productos y la muestres aquí!
?>
</p>
Figura 1-13. Esquema del circuito de una página que muestra información almacenada en una base de
datos.
Pero aquí no terminan las ventajas de almacenar en una base de datos la información de una
página, sino que PHP y MySQL agregan un camino imposible de lograr solamente con HTML:
la posibilidad de enviar datos desde el navegador del usuario hacia el servidor, y que estos
datos queden almacenados en la base de datos del hosting.
Figura 1-14. Esquema del circuito de una página que envía datos hacia el servidor.
¿Posibles usos?: envío de formularios con consultas, curriculums, formularios para pa-
neles de administración que actualizan datos de catálogos, envío de mensajes para publicar
en foros, envío de fotografías, etc.
Figura 1-15. Ejemplo de formulario que envía datos al servidor y los guarda en una base de datos.
La combinación de los dos “caminos” anteriores (enviar datos hacia la base de datos y,
luego, mostrar esos datos mediante páginas dinámicas) permiten crear sistemas denomi-
nados CMS (Content Management System o Sistemas de Administración de Contenidos)
que gestionan la publicación de contenidos de portales, sistemas de comercio electrónico,
comunidades online, y muchas otras aplicaciones, siempre sobre la base de esos conceptos
básicos: el usuario envía datos hacia el hosting, que se almacenan en la base de datos y,
luego, esos datos se muestran (a él o a otros usuarios autorizados).
Se denomina Front-end a la parte visible por los usuarios, y Back-end al panel de admi-
nistración de acceso restringido solo a los usuarios autorizados (como el de la última imagen).
Millares de CMS de uso libre y gratuito
Existen literalmente miles de CMS con distintas fnalidades, listos para usar, con licencia de
libre uso y modifcación (típicamente, la licencia GPL y similares), creados con PHP y MySQL.
Algunos de los más famosos son Joomla, WordPress, osCommerce, Mambo, Drupal, Moodle,
Magento, OpenRealty, pero existen miles más.
El secreto del negocio está en saber programar en PHP lo sufciente como para en-
tender y poder realizar algunas modifcaciones para adaptar estos CMS a las necesida-
des específcas de cada cliente, y poder ofrecerles soluciones de bajo costo y muy rápida
implementación.
Figura 1-16. Nuestro negocio: tomar código prearmado y modifcarlo según las necesidades de nues-
tros clientes.
¿Y esa primera letra, la “L”, “M”, “W” y “x”? Son las iniciales de
los sistemas operativos más usados: “L” de Linux (cualquiera de sus
miles de variantes); “M”, de Mac; “W”, de Windows. Y la “x” se usa
como un comodín, cuando se puede prescindir de un sistema opera-
tivo en particular y nos referimos a una instalación de Apache, MySQL
y PHP genérica, en cualquier sistema operativo.
Esta sigla resume el entorno bajo el cual estamos usando a
PHP. Así que, si están usando Windows y, a continuación, instalan
Apache, MySQL y PHP, estarán trabajando bajo una plataforma
WAMP (Windows con Apache, MySQL y PHP). Por el contrario, la
mayoría de los hostings se basan en LAMP (Linux, Apache, MySQL
y PHP).
El hosting
Eligiendo un buen hosting con PHP y MySQL
Sin lugar a dudas, es imprescindible para probar nuestros desarrollos que dispongamos de
un hosting, que puede funcionar bajo cualquiera de las plataformas recién mencionadas
(aunque la más recomendable es LAMP, ya que es la que más potencia permite sacarle a
PHP). ¡Atención!: esto no signifca que nosotros debamos usar Linux en nuestra computa-
dora, sino que el hosting usará ese sistema operativo. Nosotros simplemente nos conecta-
remos mediante algún programa de FTP para colocar en ese servidor nuestros archivos, y
podemos hacer esto desde cualquier sistema operativo.
Para contratar algún servicio de hosting, debemos tener en cuenta que no son todos
iguales, sino que existen distintas versiones de PHP y pueden tener instalada cualquiera de
ellas. Lo ideal es conseguir hostings que posean la versión de PHP más actualizada que nos
resulte posible: podemos consultar cuál es el número de la última versión de PHP si entramos
a la Web ofcial de PHP, en http://www.php.net
Además de buscar hostings con una versión actualizada de PHP, también debemos
intentar que posean una versión lo más actualizada que sea posible de MySQL, y del mismo
modo que con PHP, el número de versión lo averiguaremos entrando a la Web ofcial, en este
caso, de MySQL: http://www.mysql.com
Hechas esas recomendaciones, el resto es sentido común: es mejor un hosting con
soporte 24 horas, que podamos pagarlo en nuestra moneda local sin gastos de transferencia,
y que no sea el de moda ni el más barato, porque suelen tener problemas frecuentemente.
Suele ser útil que posean teléfono al que podamos llamar al costo de una llamada local para
gestionar reclamos con más efectividad que por mail o ticket de soporte. Un hosting prome-
dio, sin demasiados usuarios, suele ser mejor negocio que otro más barato pero saturado en
su capacidad de dar soporte (más que un producto, el hosting es un servicio, y es clave que
tengamos acceso a las personas que nos podrán dar ayuda en caso de necesidad, de nada
sirven esos soportes técnicos que repiten respuestas mecánicamente).
Recomiendo que usemos esa ruta, ya que todas las explicaciones del libro están arma-
das tomando como base esa ruta de instalación.
A continuación, pulsamos el botón Install, y esperamos aproximadamente un minuto
mientras extrae todos los paquetes necesarios.
Por último, se abrirá una ventana de sistema que nos preguntará algunas cosas:
i C:\WINDOWS\5V5tem32\cnid.exe
ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttitttttttttitttttittttttttt
tt XAMPP 1 . 7 . 3 - S e t u p tt
tt tt
tt C o p y r i g h t 2009 C a r s t e n Uiednann (FreeBSD L i c e n s e ) tt
tt tt
tt ñ u t h o r s : C a r s t e n Uiednann < c a r s t e n _ s t t g t P g n x _ d e > tt
tt Hay U o g e l g e s a n g < k v o G a p a c h e f r i e n d s . o r g > tt
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
Should I add startmenu/desktop? ( y / n ) :
Nos está preguntando si agrega accesos directos al menú Inicio y al Escritorio, pulsa-
mos una y para indicar que sí y, después, pulsamos Enter.
Luego, detectará que hemos cambiado la carpeta por omisión y nos pedirá que confr-
memos la modifcación de las rutas de todos los archivos de confguración (es fundamental
que aquí respondamos que sí, pulsando y y, a continuación, Enter):
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
tt KAMPP i . ? . 3 - Setup tt
tt tt
tt Copyright 2009 Carsten Uiednann (FreeBSD L i c e n s e ) tt
tt tt
tt ñuthors: Carsten Uiednann <carsten_sttgtPgnx.de> tt
tt Hay Uogelgesang <kvDGapachefriends.org> tt
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
Current directory does not natch configured directory.
I must re lócate the XAMPP paths correctly.
Should I proceed? (y/x=exit setup): JA
Acto seguido, nos preguntará si nos interesaría crear una instalación portátil –para
discos portátiles–, pero, como, por el momento, no es nuestra intención, pulsaremos la letra
n y, luego, Enter:
' C\W3MDOWS\5ystem32\cmd.exe
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
tt XAMPP i . 7 . 3 - S e t u p tt
tt tt
tt Copyright 2909 Carsten Wiednann <FreeBSD L i c e n s e > tt
tt tt
tt fluthors: C a r s t e n Wiednann < c a r s t e n _ s t t g t P g m x _ d e > tt
tt Hay U o g e l g e s a n g < k u o P a p a c h e f r i e n d s . o r g > tt
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
Should I nake a p o r t a b l e XflMPP u i t h o u t d r i u e letters?
NOTE: - Vou should use driue letters, if you uant use seruices.
- Uith USB sticks you must not use driue letters.
Vour choice? Cg/n>: o.
Figura 2-6. Manifestamos que ahora no estamos interesados en crear una instalación portable.
Ahora, realizará el cambio de confguración que habíamos autorizado dos pasos atrás,
lo que demorará unas decenas de segundos, y nos indicará que pulsemos Enter:
v C\W3MDOWS\svstem32\cmd.exe
Should I nake a p o r t a b l e JiAMPF u i t h o u t d r i u e letters?
NOTE: - Vou s h o u l d u s e d r i u e l e t t e r s , i f vou want use s
- U i t h USB s t i c k s you must not use d r i u e l e t t e r s .
Vour c h o i c e ? £ y / n > : n
r e l o c a t i n g XflMPP...
relocate XflMPP base package
reloeate Apache
relocate FileZilla FTP Seruer
r e l o c a t e Mercury
r e l o c a t e MySQL
relocate OpenSSL
relocate Perl
r e l o c a t e PHP
r e l o c a t e phpMyfldn in
relocate Sendnail
r e l o c a t e Webalizer
relocate XflMPP Denopage
r e l o c a t i n g XflMPP s u c c e s s f u l .
XflMPP i s r e a d y t o u s e .
P r e s s <Return> t o continué:
Por último, confgurará la zona horaria según lo detectado en el sistema operativo, y nos
pedirá que pulsemos Enter otra vez:
' C:\WINDOWS\5V5tenii3Z\crad.exe
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
tt XflMPP 1 . 7 . 3 - S e t u p tt
tt tt
tt Copyright 2009 Carsten Uiednann <FreeBSD LÍcense) tt
tt tt
tt fluthors: C a r s t e n Uiednann < c a r s t e n _ s t t g t P g m x . d e > tt
tt Kay U o g e l g e s a n g <3íuoPapachef r i e n d s . o r g > tt
tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
I ha ve set the timesoné in * php. ini' and ' ny. ini' to "fine ric a/Sao _Paulo".
Vou should correct these valúes if my guess uas urong.
Press <Keturn> to continué:
Figura 2-8. Autodetección de zona horaria.
Llegado este momento, nos muestra una pantalla con un menú de opciones:
1 . s t a r t XflMPP C o n t r o l P a n e l
2 . r e l o c a t e XflMPP
í c u r r e n t path: C:SseruidorSxanpp)
3 . d i s a b l e HTTPS ÍSSL)
4 . d i s a b l e S e r u e r S i d e I n c l u d e s CSSI)
5 . e n a b l e IPu4 o n l y í c u r r e n t : I P v 4 / 6 ( a u t o ) )
6. disable nod_perl
7 . d i s a b l e Apache::flSP
Figura 2-12. Alerta del Firewall de Windows, para que autoricemos el desbloqueo del servidor Web Apache.
Lo abrimos con el bloc de notas, vamos al menú Edición -> Buscar, y buscamos
error_reporting y, cuando lo encuentra por primera vez, vamos a Buscar siguiente:
Figura 2-14. Buscamos error_reporting hasta que comience sin punto y coma el renglón que contenga
esa directiva.
Simplemente, copiaremos lo que dice dentro de ese mismo archivo, tres líneas antes,
a la derecha de “Development value”, y lo pegamos a la derecha de error_reporting, para
que quede así:
Una vez hecho esto, dentro del Bloc de notas en el que estamos, vamos al menú
Archivo -> Guardar. Si teníamos encendido el servidor Web Apache, lo apagamos y volve-
mos a iniciarlo para que lea esta nueva confguración. Y, con este único cambio, ya tenemos
todo preparado como para comenzar a programar en PHP.
Esta es la única vez que vamos a tener que confgurar estas cuestiones técnicas, pro-
pias de Administradores de Sistemas y de Redes; en la vida real, todo esto ya está funcionan-
do y confgurado en los hostings que uno contrata para sus sitios Web.
Como conclusión: al servidor Web Apache lo vamos a prender cuando queramos probar
nuestros archivos PHP, es un software que “no se ve” nunca, ya vamos a entender esto al
usarlo, muy pronto.
Si, por casualidad, ya tuviéramos otro servidor Web instalado en nuestra computado-
ra (típicamente el Internet Information Server o algún otro Apache), deberemos apagarlo
cada vez que queramos usar este servidor que acabamos de instalar.
No pueden estar encendidos ambos a la vez (podrían si se confguraran los puertos de
una forma especial, pero es más fácil apagar uno y prender el otro cuando lo necesitemos
usar).
Figura 2-15. Defniremos un sitio o proyecto en la carpeta raíz del servidor local.
Por ejemplo, para el primer ejercicio del libro, crearemos una carpeta llamada “ejerci-
cio1”, que entonces va a quedar ubicada en:
C:\servidor\xampp\htdocs\ejercicio1\
Para crear los archivos PHP que daremos como ejemplo en este libro, al ir al menú
Archivo -> Nuevo del Dreamweaver, en vez de elegir Página en blanco -> HTML vamos a
elegir la última opción de esa segunda columna, la que dice PHP (esto en el Dreamweaver, en
otros editores simplemente ir a Nuevo Archivo):
Si luego de pulsar en Crear vemos la pantalla en blanco, es porque estamos trabajando
en la Vista de Diseño del Dreamweaver, debemos trabajar en Vista de Código.
En ese caso, debemos pulsar en el botón Código, y veremos el código fuente del
archivo:
Figura 2-18. Nos aseguraremos de que nuestro sistema operativo no oculte las extensiones de los
archivos.
Tenemos que asegurarnos que esté sin marcar la opción que dice Ocultar las ex-
tensiones de archivo para tipos de archivo conocidos y que quede vacío el cuadrito de
selección. Luego, pulsamos Aceptar y veremos las extensiones de los archivos en todos los
programas.
Ahora, programaremos una simple línea de código PHP para que esta página deje de
estar vacía.
Figura 2-19. Página con datos, generada por la función “phpinfo()” que ejecutamos.
Es decir, observaremos una pantalla larga, con colores celeste, azul, gris y blanco. Si la
visualizamos es porque hemos confgurado todo correctamente, y ya podemos disfrutar de
los benefcios de crear nuestra primera página con PHP (fue sufciente apenas una línea de
código para generar una página completa llena de datos, lo que no es poco, ¿no es cierto?).
Por supuesto, también deberíamos probar siempre nuestros ejercicios online, en un
hosting que soporte PHP y MySQL.
Reiteramos que es sumamente recomendable crear una carpeta por cada ejercicio
que desarrollemos, tanto en el servidor local como en el hosting que utilicemos (usualmen-
te los ejercicios y proyectos profesionales que realicemos estarán formados por numerosos
archivos, y si no los vamos ordenando desde un principio dentro de carpetas, terminaremos
mezclando todo).
Con todos los programas instalados, confgurados y probados, ¡ya podemos comenzar
a programar en PHP!
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="es" lang=”es">
<head>
<title>Hola</title>
</head>
<body>
<?php
Este archivo deberá guardarse dentro de la carpeta raíz del servidor Web que hayamos
instalado; por ejemplo, quienes hayan instalado el XAMPP en la ruta que explicamos en el
capítulo anterior, podrían crear una subcarpeta dentro de la raíz del servidor Web Apache, y
colocarlo en:
C:/servidor/xampp/htdocs/ejercicio1/hola.php
2. Encendemos el software servidor Web local (si lo instalamos usando el XAMPP,
deberemos ir al menú Inicio -> Todos los Programas -> XAMPP for Windows
-> XAMPP Control Panel).
El software servidor Web quedará a la espera de que le pidamos, a través de un nave-
gador (Explorer, Firefox, Opera), alguno de los archivos que tiene listos para servirnos. En este
caso, le pediremos el archivo hola.php.
3. Para ello, abriremos el navegador (Explorer, Firefox, Opera, Safari o cualquier
otro) y escribiremos la URL necesaria para solicitarle al servidor Web el archivo
hola.php. Este es un tema clave.
En una PC con un servidor Web local deberemos escribir:
http://localhost/ejercicio1/hola.php
o bien usando la dirección IP local:
http://127.0.0.1/ejercicio1/hola.php
Atención: no funcionará ir al menú Archivo -> Abrir del navegador, ya que nuestro
archivo PHP necesita ser procesado por el programa intérprete de PHP instalado en
el servidor Web, que debe estar encendido.
Tampoco funciona, para quienes usen Dreamweaver, pulsar F12, por la misma razón.
Ni tampoco funciona darle doble clic al archivo PHP.
En todos esos casos erróneos, si miran la URL, no mencionará en ningún lado
http://localhost/ejercicio1/hola.php. Por esta razón, el software servidor Web y el in-
térprete de PHP no procesarán ese archivo.
Una vez solicitada la URL del archivo desde nuestro navegador, y luego de esperar unos
segundos, llegará al navegador el código fuente que fue procesado en el servidor. A partir de
este momento, en el que el código generado llegó a nuestro navegador, podemos acceder
al código fuente que fue entregado a nuestro navegador (usando el menú: Ver -> Código
fuente) y, en este ejemplo, veremos que le ha llegado lo siguiente:
Es decir: el intérprete de PHP borró todas las órdenes que encontró entre las marcas
<?php y ?>, que son las que indican el comienzo y el f n –respectivamente– de una zona en
la que se va a dar órdenes al intérprete de PHP y, en lugar de lo que había escrito allí, escribió,
mediante la función print (que analizaremos seguidamente), el texto:
Los distintos tipos de tags de apertura y cierre de un bloque escrito en lenguaje PHP
que podemos llegar a encontrar, son los siguientes:
1. Apertura y cierre estándar:
<?php xxxxx ?>
o también:
<?php
xxxxx
?>
Esta es la única sintaxis universal: funciona siempre. Es la única forma recomendada,
y la que vamos a usar.
2. Apertura y cierre corto:
<? xxxxx ?>
o también:
<?
xxxxx
?>
Esta sintaxis se conoce como short tags (etiquetas cortas). Fue muy usada en los pri-
meros años de PHP, pero no es estándar. No todas las confguraciones del intérprete
de PHP habilitan su uso, por lo que un código que utilice esta sintaxis puede dejar de
funcionar al ser ubicado en un servidor con otra confguración más estricta. Por ese
motivo, no la recomendamos.
3. Apertura y cierre mediante etiqueta script:
<script language=“php”> xxxxx </script>
o también:
<script language=“php”>
xxxxx
</script>
Esta sintaxis, si bien todavía se soporta, es innecesariamente larga y es rarísimo en-
contrar algún código que la emplee. Por lo tanto, al no tener ninguna otra ventaja
añadida, no recomendamos su uso.
4. Tags estilo ASP:
<% xxxxx %>
o también:
<%
xxxxx
%>
Sintaxis al estilo del lenguaje de programación ASP de Microsoft: no es estándar, la
posibilidad de usarla depende de la confguración del intérprete; por lo tanto, tampoco
se recomienda su utilización.
En los ejemplos anteriores, hemos utilizado la función print, que “escribe” en el código
fuente de la página que está por enviarse instantes después desde el servidor hacia al nave-
gador del usuario, y que, como vemos, puede escribir no solamente texto, sino también eti-
quetas HTML como el “<p>” o “<h1>” del ejemplo, etiquetas que luego son interpretadas por
el navegador como cualquier otro código HTML que hubiese estado escrito allí originalmente.
Veamos cómo trabaja esta función.
Ya hemos utilizado intuitivamente esta función en los ejemplos anteriores. Si lo que de-
seamos es que se escriba en el código de la página un texto, literalmente, debemos escribirlo
entre comillas dentro de sus paréntesis.
Ejemplo:
<?php
print("hola");
?>
Si sólo tuviéramos que escribir textos y nunca código HTML, no tendríamos problemas
pero, como debemos encerrar entre comillas el texto a mostrar, se nos planteará un problema
a la hora de escribir código HTML que, a su vez, tenga comillas dentro.
En el siguiente ejemplo, veremos por qué:
<?php
print("<h1 class="portada">Bienvenidos</h1>");
?>
Este ejemplo generará un error, pues la comilla ubicada luego del signo = está cumplien-
do, sin querer, la función de cerrar la primera de las comillas –la que se abrió al inicio del print,
luego del paréntesis inicial– y, por lo tanto, el tramo de texto se da por concluido y al resto
que sigue a esa comilla el software intérprete de PHP no sabe cómo tratarlo, y lo advierte
mostrando un mensaje de error en la pantalla.
Una posible solución al problema de las comillas es desactivar (a esto se lo denomina
“escapar”) todas las comillas dobles intermedias, una por una, para que no den por concluida
la cadena de texto antes de que lleguemos a la última comilla doble que indica el término de
la función print.
El carácter de escape es la barra invertida \ y sirve para no ejecutar el carácter que le
sigue inmediatamente como si fuera parte de una orden del lenguaje PHP, sino que lo consi-
dera como una letra más que debe ser escrita literalmente.
Por esta razón, el ejemplo anterior quedará así:
<?php
print("<h1 class=\"portada\">Bienvenidos</h1>");
?>
Esto funciona muy bien en frases cortas, pero el mayor inconveniente o molestia que nos
puede causar surge cuando tenemos que imprimir largos bloques de código HTML, ya que es
muy probable que esos bloques (tal vez páginas enteras) ya los tengamos escritos de antes,
generados por nuestro editor de código HTML, y es casi seguro que poseerán numerosas co-
millas dobles. En esos casos, estaríamos obligados a la tediosa tarea de encontrar las comillas
una por una, y “escaparlas” anteponiéndoles una barra invertida o, en su defecto, podríamos
utilizar las herramientas de búsqueda y reemplazo de caracteres de algunos editores HTML
para buscar una comilla y reemplazarla por la barra de escape más la comilla. Pero, en ambos
casos, sería una larga y aburrida tarea.
Mucho mejor que esto, sería utilizar comillas simples para delimitar el inicio y fnal del
bloque de texto a imprimir:
<?php
print('<h1 class="portada">Bienvenidos</h1>');
?>
¡Y problema solucionado!
<?php
echo "Hola Mundo entre comillas dobles!";
echo '<html>
<head>
<title>Envuelvo entre comillas simples</title>
</head>
<body>"Esto tiene comillas dobles, "muchas comillas", y no
importa"
</body>
</html>';
?>
Notemos de paso que el código que escribirá puede estar dividido en múltiples líneas
(PHP ignora tanto los saltos de línea como los espacios en blanco), y también señalemos otro
detalle al que todavía no habíamos prestado atención: para dar por terminada una sentencia
u orden, se agrega un punto y coma al fnal de la línea.
heredoc, que nos permite escribir grandes cantidades de texto, sin necesidad de escapar
caracteres en su interior.
Su uso es muy simple. Al inicio del bloque de texto, debemos colocar tres veces el signo
“menor que”, de esta manera: <<< seguido de varios caracteres alfanuméricos (en el ejemplo
que sigue hemos elegido EOT, pero pudo ser cualquier otra combinación de letras); luego,
pegamos el bloque de texto y código HTML que escribiremos y, para fnalizar, repetimos los
mismos tres caracteres que indicaron el inicio del bloque:
<?php
echo <<<EOT
<p>Este texto puede tener dentro "comillas" sin necesidad
de escaparlas.</p>
<p>También procesa (reemplaza por su valor) las $variables
que hubiera dentro del código, tema que veremos próximamente.</
p>
<p>Esta construcción del lenguaje llamada heredoc es ideal
para incluir largos bloques de código HTML.</p>
EOT;
?>
<?php
$codigo = <<<EOT
<p>Este texto puede tener dentro "comillas" sin necesidad de
escaparlas.</p>
<p>También procesa (reemplaza por su valor) las $variables
que hubiera dentro del código, tema que veremos próximamente.</
p>
EOT;
echo $codigo;
?>
Si bien los caracteres identifcadores pueden formarse con cualquier combinación al-
fanumérica, por convención, se suele utilizar los caracteres EOT (end of text o fnal de texto).
Lo importante es que esos mismos caracteres no estén incluidos dentro del texto, ya que de
suceder eso, el software intérprete de PHP considerará que allí termina el bloque, y provocará
un mensaje de error al no saber qué hacer con el resto de texto.
Otra consideración es que estos caracteres indicadores del inicio y fn del bloque, deben
incluirse justo al comienzo del renglón (sin dejar ni un solo espacio en blanco, ni tabuladores,
indentados de código, ni comentarios), y tampoco deben contener ningún otro carácter al
fnal, salvo el punto y coma que fnaliza el echo (y, luego del punto y coma, debe haber un
salto de línea).
Por ese motivo, si escribimos este código en un editor de texto bajo Windows, pode-
mos tener problemas al incluir el salto de línea (Enter) al fnal del renglón, ya que el salto de
línea en Windows no es el carácter de nueva línea \n que esta construcción espera encontrar,
sino que es \r\n.
Podemos hacer la prueba y, si vemos que al terminar la orden no se interrumpe la escri-
tura del texto, deberíamos verifcar que el renglón fnal esté completamente vacío de cualquier
carácter extraño. Una vez confrmado que nuestro editor esté generando el salto de forma
correcta, conviene que subamos al servidor por FTP el archivo empleando el modo Ascii (y
no el binario), y desactivar la opción de “autodetectar” que la mayoría de programas de FTP
contienen.
Además de la facilidad de lectura y pegado en su lugar de los largos bloques de código,
esta sintaxis incrementa la velocidad de interpretación del código en el servidor si la compa-
ramos con el uso de varios echo o print seguidos.
Luego, en cada página del sitio donde necesitemos mostrar ese menú o ese pie, le
ordenaremos al software intérprete de PHP que incluya el código completo del archivo en
cuestión en el lugar exacto en el que lo especifquemos. Esta orden realiza automáticamente
una tarea similar a la que haríamos manualmente si seleccionáramos el código de esos archi-
vos externos (menu.php, pie.php, etc.), los copiáramos y los pegáramos luego en cada una
de las páginas en las que queremos mostrar ese pie o ese menú.
De esta manera, cuando fuera necesario realizar un cambio a alguno de esos archivos,
lo haremos en el archivo que contiene exclusivamente el código del menú, o el del pie de
página, y terminados los cambios de contenido de esos archivos únicos, los subiremos por
FTP, y no tendremos que cambiar absolutamente nada en las otras decenas, o cientos, o
miles de páginas que conforman el sitio, que refejarán los cambios de inmediato, ya que en
ellas sólo dice “mostrar aquí lo que haya en menu.php” (de una forma más técnica, pero la
idea es esa).
Veamos un ejemplo, el archivo pagina.php:
Figura 3-1. Ejemplo de archivo que integra otros archivos incluyéndolos en él.
El código de este archivo pagina.php –que simula ser una de las tantas páginas están-
dar del sitio– quedaría de la siguiente manera:
<div id="contenidoPrincipal">
Contenido principal
</div>
Y, admás, tendríamos un archivo por cada bloque de página que deseamos independizar:
El archivo encabezado.php:
<div id="encabezado">
Encabezado
</div>
El archivo botonera.php:
<div id="botonera">
Botonera
</div>
El archivo pie.php:
<div id="pie">
Pie
</div>
Queda claro entonces que include nos brinda un enorme ahorro de tiempo a la hora de rea-
lizar tareas de mantenimiento de un sitio de muchas páginas.
Más adelante también utilizaremos include para colocar en archivos externos decla-
raciones de variables, funciones, clases y de cualquier otra información que sea necesario
mantenerla disponible a lo largo de muchas páginas, pero sin repetirla, declarándola y alma-
cenándola una sola vez en un archivo externo que será incluido por todas aquellas páginas
que necesiten la información que estos archivos externos contienen.
<div id="contenidoPrincipal">
Contenido principal
</div>
Los comentarios
Realizar comentarios dentro del código PHP es una muy simple pero muy efcaz costumbre,
que consiste en ir escribiendo dentro de cada bloque de código aclaraciones que nos sean
de utilidad cuando, varios días, semanas o meses después, volvamos a leer el código para
hacerle alguna modifcación. Recordemos que estos comentarios no llegan al código fuente
del navegador, por lo que los usuarios de nuestros sitios no los pueden ver, ya que son para
nuestro uso personal y el de otros programadores que tengan acceso a nuestro código.
El objetivo de envolver algo entre comentarios es lograr que el software intérprete de
PHP no intente ejecutar las palabras que escribamos, sino que las ignore, y prosiga luego de
fnalizado el comentario.
PHP permite escribir comentarios de una o varias líneas:
<?php
$variable = "valor"; //comentario de una línea
$cifra = 123; #otro comentario de una línea
Un uso práctico es aclarar cosas que sea útil recordar más adelante, al revisar este
código:
<?php
$clave = "xyz345"; // recordar avisar al Gerente si la
cambiamos
$tolerancia = 3 ; # es la cantidad de reintentos de ingreso
tolerados con una contraseña equivocada
Otro uso muy práctico de los comentarios es “desactivar” renglones de código que
queremos que no se ejecuten, pero que no tenemos la intención de borrarlos, sino que sólo
queremos ejecutar el archivo sin que se ejecuten las líneas del código comentadas. Comen-
tamos partes del código, y es como si no existieran. Esto nos ayuda en la detección de
errores, si comentamos alguna línea cercana a la zona en que está produciéndose un error,
para evitar su ejecución y ayudarnos a detectar qué es lo que lo está produciendo, tema que
practicaremos más adelante.
Como acabamos de ver, uno de los principales usos de PHP es ayudarnos a completar
ciertas partes de nuestras páginas Web, escribiendo textos y código HTML en el acto, unos
breves instantes antes de que el servidor Web envíe ese código “terminado” hacia el navega-
dor del usuario. Esta tarea de escritura –que va desde el agregado de unos pocos caracteres
hasta la inclusión de archivos HTML enteros– aunque puede parecer muy simple, es de una
enorme potencia que ya iremos comprendiendo a lo largo de este libro, y resulta imprescindi-
ble para crear páginas Web “dinámicas”, con contenidos que, según la ocasión, pueden ser
muy distintos. El punto clave es que esos textos, esa información que será escrita dentro del
código HTML, se obtendrá automáticamente, de muy distintas fuentes, tales como variables,
constantes, matrices, funciones, archivos de texto y bases de datos. En el siguiente capítulo,
comenzaremos a familiarizarnos con algunos de estos lugares en los que se almacena la
información.
Contenedores temporales y
permanentes, de pocos y de
muchos datos
En los capítulos precedentes, le indicamos al intérprete de PHP los
contenidos que debía escribir dentro de cada orden print() o echo. Le
proporcionamos, además, cada uno de los datos con los que trabajó
y le dictamos todo lo que escribió.
Pero, paradójicamente, la utilidad de PHP radica en entregarle a
un navegador Web (Firefox, Explorer, Opera, o el que fuere) diferentes
contenidos, según se vayan desencadenando ciertos sucesos previs-
tos por el programador de la página (de acuerdo con la contraseña
introducida, el enlace pulsado, un dato que se valida, etc.).
Este comportamiento se denomina páginas Web dinámicas;
es decir: el navegador, luego de solicitar una URL, recibirá como res-
puesta una página Web que no fue escrita en su totalidad por el di-
señador o programador con su programa editor, sino que su código
–todo, o al menos una parte– lo escribirá el intérprete de PHP cada
vez que un usuario pida ver esa página con su navegador; por lo
tanto, la página se construirá “en vivo” en el servidor, unos instantes
antes de que la envíe hacia el navegador.
Esto nos lleva a una pregunta obvia: si no somos nosotros (di-
señadores, programadores) quienes le dictaremos letra por letra al
intérprete de PHP esos textos, ¿de dónde obtendrá esos datos? La respuesta es “de varios
lugares posibles”.
De acuerdo con cada una de nuestras necesidades específcas, dispondremos de
distintas alternativas para almacenar datos en lugares a los que accederemos desde el
servidor, donde el intérprete de PHP podrá leerlos por sí mismo y los utilizará para su tarea
de fabricar una página HTML. Mencionaremos, a continuación, algunos de esos posibles
lugares -los principales-, para que nos vayamos imaginando los recursos con los que
trabajaremos:
• Los datos se podrán almacenar en una variable -o en una matriz (creada por
nosotros, o una de las tantas matrices en las que el intérprete de PHP almacena
información automáticamente)-.
• El usuario podrá ingresar los datos y, consciente o inconscientemente, usará su
navegador para enviar las variables hacia el servidor, ya sea a través de un for-
mulario o mediante las variables adjuntadas a una URL, con un tipo de enlace
especial. Un envío de “señales” hacia el servidor que nuestra página PHP estará
esperando para decidir qué información mostrar.
• Los datos también se podrán obtener como resultado de ejecutar una función
(de las que vienen incluidas en el lenguaje PHP, o de las funciones que crearemos
nosotros mismos).
• Un dato se podrá almacenar en una cookie que el navegador del usuario guardará
silenciosamente.
• Se podrá leer un dato de una variable de sesión, lo que nos permitirá identifcar a
un usuario en particular en un momento dado.
• Se podrán leer los datos escritos dentro de un archivo de texto (txt, XML, etc.)
existente en el servidor.
• Se podrán leer los datos almacenados en una base de datos (sin dudas, la opción
más poderosa para manejar grandes cantidades de datos, como catálogos de
productos, mensajes de foros, etc.).
Todo el resto de este libro consistirá en aprender a leer y a escribir datos en estos
lugares.
Comenzaremos aprendiendo a trabajar con el almacén de datos más simple y más
universalmente utilizado: las variables.
De una forma más gráfca y simplifcada, una variable es una especie de «caja etique-
tada» que almacena algún dato hasta que necesitemos usarlo.
Usamos variables a diario; por ejemplo, guardamos dinero en un cajón y luego
decimos: “usemos el dinero que hay en el primer cajón”. “Primer cajón” sería el
nombre de una variable, que a veces contendrá un valor de «0» (si no hay dine-
ro), y a veces contendrá una cantidad “X” de dinero; es decir, su contenido no será
siempre el mismo, a lo largo del tiempo podrá variar, de allí su nombre “variable”.
Cualquier receta de cocina está llena de variables (la cantidad de cada ingrediente,
es una variable).
¡Incluso los seres humanos estamos llenos de variables! Cuando en un formulario nos
dicen “Escriba aquí su nombre”, “su nombre” es una variable, ese casillero conten-
drá “Hernán”, en mi caso, pero contendrá cualquier otro nombre en el caso de que
alguien no sea tocayo mío. Todo lo que puede describirse cuantitativa o cualitativa-
mente es un dato que puede almacenarse en una variable. El peso, la altura, la edad,
el apellido, la nacionalidad, la ocupación, el teléfono, etc. Variables y más variables.
Textos y números: datos.
Una variable siempre tiene dos elementos: un nombre (siempre el mismo, así como
“Primer cajón” será siempre “Primer cajón”, y gracias a esa invariabilidad podemos referirnos
a él sin lugar a confusiones como “Primer cajón”), y un valor (el dato que almacenamos dentro
de ella) que a diferencia del nombre, sí puede variar:
Podemos observar, en este ejemplo, algunos detalles de sintaxis: en el lenguaje PHP las
variables se crean anteponiéndole un signo $ al nombre que le queramos dar a la variable (sin
dejar ningún espacio entre el signo y la primera letra del nombre de la variable).
Y se les almacena un valor mediante el signo igual, al que técnicamente lo denomina-
remos “Operador de asignación”, ya que, precisamente, sirve para asignarle un valor a una
variable.
Veamos otros ejemplos para seguir comprendiendo esta sencilla sintaxis:
<?php
$nombre = "Pepe";
print($mensaje);
?>
La vida de una variable en PHP es muy breve: dura apenas unas pocas décimas de
segundo. En el momento en que el intérprete de PHP lee la declaración de una variable, ésta
comienza a existir; acto seguido, la podrá utilizar para alguna cuestión (podría ser una orden
escrita que le hayamos dejado al intérprete de PHP para que utilice o muestre esa variable,
para que realice alguna operación con ella) y, en cuanto el intérprete de PHP haya terminado
la lectura y proceso del código PHP de esa página Web completa (menos de un segundo,
habitualmente) y haya entregado el código HTML ya procesado al servidor Web para que lo
envíe al navegador que estaba esperando su respuesta, en ese instante, el intérprete de PHP
borrará de la memoria RAM del servidor Web todas las variables que hubieran sido declara-
das durante el breve tiempo que demoró el procesamiento de esa página.
Muy pronto comprenderemos la simplicidad pero, a la vez, la enorme fuerza de este
concepto, que deja depositado un dato provisoriamente en la memoria de un servidor.
<?php
$dato_123 = "Pepe";
$dato_46 = "Hola, señor $dato_123";
print($dato_46);
?>
Imagínense esto proyectado a cientos o miles de líneas de código (algo que será común
en nuestros proyectos). ¡Imposible de entender a simple vista!
Además de los nombres descriptivos, otra recomendación es que no conviene mezclar
nombres de variables en mayúsculas y en minúsculas. Lo mejor es seguir algún criterio, al-
guna convención, ya que es ésta una de las causas más frecuentes de errores que nos hacen
perder tiempo al tratar de descubrir la causa.
La razón es que PHP es un lenguaje case-sensitive, o “sensible” a mayúsculas y a
minúsculas; es decir, no es lo mismo $a –en minúsculas– que $A –en mayúsculas–: para
PHP son dos variables distintas. No es la misma variable una que se llame $nombre que otra
llamada $Nombre o que $nomBRE. Y si habíamos defnido $Nombre y después hacemos un
echo de $nombre... ¡no funcionará! Y con justa razón, ya que no existe la variable que intenta-
mos leer, existe otra con una letra de diferencia, y eso la vuelve totalmente distinta.
Por eso es sumamente recomendable que sigamos alguna regla para nombrar nuestras
variables, y que la mantengamos a lo largo de todos nuestros proyectos.
Por ejemplo, algunas convenciones comunes relativas a los nombres de las variables,
son las siguientes:
1. Todo en minúsculas:
$variable
$mivariablelarga
2. Todo en minúsculas, pero con guiones bajos entre palabras, si el nombre de una
variable tiene varios términos:
$variable
$mi_variable_larga
3. En minúsculas la primera palabra –o si la variable es de una sola palabra–, pero
colocando una mayúscula al comienzo de cada nueva palabra intermedia, en el
caso de que el nombre de la variable tuviera más de un término. Esta notación se
llama camel case –porque las subidas y bajadas de las mayúsculas intercaladas
entre medio ¡parecen las jorobas de un camello!–. Un nombre muy imaginativo...
Esta es la sintaxis más extendida, y es la más recomendable:
$variable
$miVariableLarga
4. Cada palabra comienza siempre con mayúscula, aunque la variable sea de una
sola palabra:
$Variable
$MiVariableLarga
Más allá de cuál de todas estas convenciones elijamos, es recomendable elegir una sola
de estas notaciones –cualquiera de las anteriores– y seguir siempre la misma, eso nos evitará
muchísimos errores.
Cuando tengamos códigos de cientos de líneas (o sea, muy pronto, ¡antes de lo que
imaginamos!) será muy importante que podamos leer ese código con la velocidad con que
leemos un texto cualquiera, y que sea posible entender ese código con una sola lectura su-
perfcial, por eso es preferible que nos acostumbremos desde un principio a utilizar nombres
que sigan alguna regla de sintaxis que nos resulte cómoda.
Mencionemos, por último, que en el lenguaje PHP no podemos comenzar el nombre
de una variable con un número: las variables deben comenzar por una letra o por un guión
bajo, aunque luego sí pueden incluir números en su nombre, letras de la “a” a la “z” y guiones
bajos.
No utilizaremos eñes, ni acentos, ni espacios en blanco, ni guión medio, ni caracteres
especiales como asteriscos o cualquier otro signo en los nombres de nuestras variables.
Veamos algunos ejemplos de nombres de variables, correctos e incorrectos:
<?php
$lugar1 = "Buenos Aires"; /* Correcto, puede comenzar por
una letra */
$_lugar_2 = "México"; /* Correcto, puede comenzar por un
guión bajo */
$3_lugar = "España"; /* Incorrecto, no puede comenzar por
un número */
?>
Releamos el código anterior a este título. Allí se realizan tres operaciones de asignación de valor
a tres variables distintas. Si miramos a la derecha del signo =, veremos que el valor de esas
variables está envuelto entre comillas. Podemos deducir si observamos los distintos ejemplos
anteriores, que los valores alfanuméricos deben envolverse entre comillas, ya sean simples o
dobles; y que, en cambio, los valores numéricos no deben envolverse entre comillas.
Para almacenar un dato alfanumérico dentro de una variable, deberemos comprender
cómo son afectados esos datos al ser delimitado su inicio y su f n por los dos tipos de comillas
existentes: comillas dobles y comillas simples.
Pero veamos cómo incide esto cuando a esos textos les agregamos variables.
La interpretación de variables dentro de comillas.
Ya hemos visto cómo se comportan el comando echo y la función print (ambos son iguales
en esto):
• Cuando deseamos que el intérprete de PHP escriba un texto literalmente usare-
mos comillas simples para delimitar el inicio y el fnal de ese texto. La única limita-
ción, es que no podremos incluir comillas simples dentro de ese texto (deberemos
escaparlas), y cualquier variable que incluyamos dentro de algo envuelto entre
comillas simples, no será reemplazada por su valor.
• En cambio, cuando queremos que se interpreten y reemplacen las variables por
su valor, usaremos comillas dobles para delimitar el inicio y el fnal del bloque de
texto.
Veamos un ejemplo:
<?php
$comillasDobles = "Texto entre comillas dobles, puede
contener 'comillas simples' dentro sin problemas";
$comillasSimples = 'Texto entre comillas simples, puede
contener "comillas dobles" pero sin variables dentro, porque
usamos comillas simples para delimitar el inicio y fn del
bloque';
Concatenación
En el último ejemplo anterior a este título ($variablesSimples), nos hemos encontrado con
un problema muy común: tener un texto envuelto entre comillas simples, y necesitar que las
variables incluidas dentro se reemplacen por su valor.
Otras veces, al dictarle al intérprete de PHP largos bloques de código HTML (con abun-
dantes comillas dobles incluidas), por comodidad elegiremos delimitar el inicio y el fnal entre
?>
Para solucionarlo y lograr que esa variable se reemplace por su valor, usaremos una
técnica denominada concatenación. Concatenar es unir, es “pegar” elementos que estaban
separados. Esos elementos serán, en nuestro caso, los textos, las variables y las constantes
que necesitemos procesar. Nos basaremos en la idea sencilla de “sacar afuera” de las comi-
llas las variables y constantes que queramos reemplazar por su valor. Es decir, interrumpire-
mos momentáneamente el bloque de texto delimitado por comillas y, luego de la variable, lo
reiniciaremos.
Para esta tarea, es decir, para fnalizar y recomenzar tramos de texto, usaremos el ope-
rador de concatenación, que no es más que un simple punto: “.”
Ese punto será el “pegamento” que unirá todo aquello que nos convenga mantener a
salvo de las comillas del bloque, pero manteniéndolo unido a él. Veamos algunos ejemplos
para entenderlo mejor:
1. Entre un texto y una variable:
<?php
$nombre = 'Pepe';
$concatenacion = '<p id="saludo">Hola '.$nombre.'</p>';
?>
Visualicemos mejor los tres “tramos” que componen esta unión de partes, miran-
do cada parte por separado:
1. '<p id="saludo">Hola'
2. $nombre
3. '</p>';
Son esos tres tramos los que estamos pidiendo que sean escritos (o mejor dicho,
en este caso, que sean almacenados dentro de la variable llamada $concatena-
cion). Primero se escribirá la apertura de la etiqueta de párrafo con su identifcador
que usa comillas dobles para envolver su valor, luego se une esto al valor que
tenga la variable $nombre (Pepe, en este caso) y, fnalmente, se cierra la etiqueta
de párrafo.
Ese código producirá este resultado:
<?php
$nombre = 'Juan';
$apellido = 'Pérez';
$concatenacion = '<p>Su nombre y apellido es
$nombre.$apellido.'</p>';
?>
Vemos que pueden unirse no solamente un texto a una variable, sino también dos
variables entre sí, aunque esto generó un pequeño detalle visual: el nombre y el
apellido quedarán “pegados” entre sí, ya que no hemos incluido ningún espacio
entre ambas variables:
<?php
$nombre = 'Juan';
$apellido = 'Pérez';
$concatenacion = '<p>Su nombre y apellido es '.$nombre.
.$apellido.'</p>'
?>
Por ejemplo:
<?php
$precio = 100;
$cantidad = 5 ;
$total = $precio * $cantidad;
/* $total contiene 500 */
$aumento = 2 ;
$total = $total + $aumento;
/* $total ahora contiene 502 */
?>
primero se procesó el término que está a la derecha del signo igual; es decir, el intérprete de
PHP realizó el reemplazo de estas variables por sus valores:
$total + $aumento;
500 + 2
O, lo que es lo mismo:
502
Una vez terminada esa operación y reducidos los elementos del término de la derecha a
un solo valor, ese valor fue asignado como nuevo valor de la variable $total, mediante el signo
=, que es el operador de asignación; lo que sería lo mismo que simplifcar todo el término
derecho ya resuelto de esta manera:
$total = 502;
Así, no sólo hemos visto que una misma variable puede reutilizarse, sino que hemos
visualizado cómo se va procesando el código PHP, paso a paso, antes de asignarle valor a
una variable.
Hemos visto sufcientes detalles acerca del uso de variables. Ahora, ya estamos pre-
parados para utilizar variables en los siguientes capítulos para cosas más interesantes que las
de estos sencillos ejemplos.
<?php
defne("PI", 3.1415926);
defne("BR", "<br / > " ) ;
defne("LIBRO", "PHP 6, de Hernán Beati");
print(PI);
print(BR);
print(LIBRO);
?>
Muy importante: al momento de mostrar constantes (con echo o print), las cons-
tantes no van entre comillas (no son una cadena de texto a imprimir literalmente) ni
llevan un signo pesos delante (no son una variable).
Includes de constantes
Es una muy buena idea defnir todas las constantes de un sitio Web en un archivo aparte,
y luego incluir ese archivo (mediante include o require) en todas las páginas que necesiten
utilizar esas constantes. Es una técnica muy utilizada en sitios multilingües, que defnen cons-
tantes para los textos y usan un archivo para defnir esos textos en cada idioma.
Veamos un ejemplo de esta técnica: imaginemos un sitio Web con versión en español y
en inglés. Existirán dos archivos que almacenarán constantes, uno con los textos en español
y, otro, con los textos en inglés. Por ejemplo, dentro de la carpeta lenguajes crearemos un
archivo llamado english.php que contendrá solamente esto (notemos que no incluimos nada
de código HTML, ya que este archivo solo está almacenando datos que serán mostrados
dentro de otro archivo que ya tiene su propio código HTML completo):
<?php
defne('NAVBAR_TITLE', 'My Account');
defne('HEADING_TITLE', 'My Account Information');
defne('OVERVIEW_TITLE', 'Overview');
defne('OVERVIEW_SHOW_ALL_ORDERS', '(show all orders)');
defne('OVERVIEW_PREVIOUS_ORDERS', 'Previous Orders');
?>
<?php
defne('NAVBAR_TITLE', 'Mi Cuenta');
defne('HEADING_TITLE', 'Datos de Mi Cuenta');
defne('OVERVIEW_TITLE', 'Resumen');
defne('OVERVIEW_SHOW_ALL_ORDERS', '(ver todos mis pedidos)');
defne('OVERVIEW_PREVIOUS_ORDERS', 'Pedidos Anteriores');
?>
De esta manera, con indicar dentro de cada página el idioma que se mostrará (típi-
camente con una variable de sesión, tema que veremos más adelante), podremos incluir el
archivo de textos correspondiente al idioma elegido por el usuario.
Por ejemplo, si preparamos una página llamada cuenta.php que debe mostrar esos
textos en castellano, su código será similar a esto:
Luego será otro tema ver cómo podríamos hacer para obtener el dato de cuál idioma
prefere el usuario (mediante una variable de sesión, como dijimos, sería lo ideal) y utilizarlo en
lugar de la palabra “castellano” dentro de la ruta del include, pero eso lo dejamos para más
adelante.
Notemos que no hemos incluido constantes dentro de bloques de texto delimita-
dos con comillas simples o dobles, como hacemos cuando queremos asignar un valor a una
variable, ya que esto no funcionaría. Tampoco funcionaría colocarlas dentro de un echo o print
junto con un texto envuelto entre comillas.
Veamos por qué:
<?php
?>
</body>
</html>
Podríamos decir que, si una variable era una bicicleta que acarreaba una sola peque-
ña caja con su carga, las matrices equivaldrían a un camión cargado con decenas,
cientos o miles de cajas, cada una guardando un dato diferente, pero todos dentro
del mismo contenedor (el camión).
Otra comparación: si una variable era un estante único (y muy pequeño) en el que úni-
camente podíamos guardar un solo libro, comparativamente, una matriz equivaldría a
un gran estante en el que entran decenas de libros o, incluso, una biblioteca completa,
con decenas de estantes a la vez. Muchos libros, muchos estantes, pero todos dentro
de una misma biblioteca, de un mismo elemento contenedor.
Veamos un par de ejemplos que nos aclararán un poco más la diferencia entre una
variable y una matriz.
Este código declara y adjudica valor a una variable:
<?php
$numero = 514;
print ($numero);
// escribe 514.
?>
<?php
$numeros[0] = 7 5 ;
$numeros[1] = 9 0 ;
$numeros[2] = 4 5 ;
print ($numeros[0]."<br />".$numeros[1]."<br
/>".$numeros[2]);
// escribirá: 75<br />90<br />45
?>
<?php
$paises[0] = "Afganistán";
$paises[1] = "Albania";
$paises[2] = "Alemania";
$paises[3] = "Andorra";
$paises[4] = "Angola";
Será sumamente común el utilizar matrices como almacén provisorio de datos prove-
nientes de un almacén permanente de datos, tal como una base de datos o un archivo de
texto plano.
Distintas funciones de PHP que ya veremos en otros capítulos, se encargarán de ubi-
car dentro de matrices los datos leídos de una base de datos (como la lista de países para
mostrarlos en un menú de selección HTML de un formulario, por ejemplo, o el listado de los
distintos productos de un sitio de comercio electrónico, incluyendo su nombre, descripción,
precio, imagen, etc.), y será muy fácil trabajar con esa matriz como depósito temporal de da-
tos, típicamente utilizando un bucle para recorrerla (algo que veremos muy pronto).
Índices numéricos
Las matrices pueden utilizar dos tipos de índices: numéricos (los que vimos hasta ahora) y
alfanuméricos.
Comenzaremos a ver cómo se cargan datos en las matrices de índices numéricos.
Hay diferentes maneras de “inicializar” una matriz de índices numéricos (esto es, darle
un índice y un valor a cada una de sus celdas; es decir: colocar datos dentro de ella). Pode-
mos realizar esa tarea de forma explícita, de forma implícita, mezclando ambas formas,
o usando el constructor array. Veremos, a continuación, cada una de estas posibilidades.
Declaración explícita:
$paises[0] = "Afganistán";
$paises[1] = "Albania"; // etc.
print ($paises[0]);
print ($paises[1]); // etc.
Declaración implícita:
Pero también podríamos haber realizado el mismo ejemplo con una declaración implícita
de índices, de la siguiente manera (notemos los corchetes vacíos en el primer renglón):
<?php
$paises[] = "Afganistán"; // esta es una declaración
implícita, dejando vacíos los corchetes.
$paises[1] = "Albania";
$paises[2] = "Alemania";
$paises[3] = "Andorra";
$paises[4] = "Angola";
ya que no estamos diciendo cuál de las celdas de la matriz queremos mostrar. Siempre
dentro de los echo o print deberemos especifcar explícitamente el índice al que queremos
acceder.
Mezcla de declaración explícita e implícita:
También podría suceder que quisiéramos especifcar un índice en particular para la primera
celda de la matriz, y luego sí dejar que el intérprete siga colocando los índices automática-
mente, pero a partir de ese valor inicial que nosotros especifcamos:
$dias[] = "Martes";
$dias[] = "Miércoles";
$dias[] = "Jueves";
$dias[] = "Viernes";
Al haber especifcado nosotros uno de los índices, pero no los siguientes, PHP conti-
núa la numeración desde el valor siguiente al último índice especifcado.
La función array:
Esta declaración implícita de índices numéricos es la misma que PHP emplea cuando utili-
zamos una forma mucho más simple y más breve de declarar matrices, mediante el uso de
la función llamada array, cuya sintaxis veremos a continuación:
<?php
$paises = array("Argentina", "Uruguay", "Chile", "Perú");
// crea una matriz llamada $paises de cuatro elementos con
índices numerados a partir de cero.
$loteria = array(23,8,36,12,99);
// crea una matriz de cinco elementos con índices numerados
a partir de cero.
Como vemos en el último caso, una única matriz puede almacenar datos de distinto
tipo (caracteres, números enteros, decimales, etc.) y, por lo tanto, es necesario colocar entre
comillas los textos para que PHP sepa que son eso, textos, y no números.
También notemos que simplemente una coma separa un dato de otro.
Tal como en la mezcla de asignación explícita e implícita de índices vista anteriormente,
cuando usamos la función array también podemos forzar el índice de uno de los elementos
de la matriz (no necesariamente debe ser el primero de ellos), y eso se realiza con el operador
=> de la siguiente manera:
<?php
$paises = array(1 =>"Argentina", "Uruguay", "Chile",
"Perú");
// crea una matriz llamada $paises de cuatro elementos,
cuyo primer elemento posee un " 1 " como índice, el segundo un 2
ucesivamente.
?>
Como dijimos, no es necesario que sea el primer elemento aquel al cual le forzamos un
índice:
<?php
$paises = array("Argentina", 10 => "Uruguay", "Chile",
"Perú");
// crea una matriz llamada $paises de cuatro elementos,
cuyo primer elemento posee un " 0 " como índice, el segundo un
"10" y luego el resto continúa con "11" y " 1 2 " .
?>
Es bastante común que los índices asignados a una matriz sean números salteados, no
consecutivos como, por ejemplo, códigos de artículos. En ese caso, a medida que agre-
gamos datos al vector, puede suceder que los índices no sean consecutivos y queden
desordenados.
Por ejemplo:
<?php
$productos[1234] = "Televisor LG de 42 pulgadas";
$productos[145] = "Televisor Sony de 29 pulgadas";
$productos[899] = "Televisor portátil de 12 voltios";
?>
Índices alfanuméricos
En muchos casos, en especial cuando trabajemos con bases de datos, defnir los índices
de la matriz con cadenas de texto (alfanuméricas) en lugar de utilizar números, será de
mucha utilidad para facilitar la lectura del código.
En PHP se puede hacer de la siguiente manera:
<?php
$datos["nombre"] = "Juan Pérez";
$datos["edad"] = 2 4 ;
$datos["estado"] = "casado";
$datos["sueldo"] = 800;
Un caso especial dentro de las matrices de índices alfanuméricos, son aquellas matrices que
el intérprete de PHP declara y completa con datos automáticamente, sin que nosotros ten-
gamos que hacer nada, tan solo leerlas y utilizar la información que nos proporcionan.
Ya que la lista de los posibles valores de índices alfanuméricos de estas matrices es
muy extensa (a veces, decenas de valores posibles en cada matriz), recomendamos consultar
el manual ofcial de referencia de PHP en línea, en: http://www.php.net agregando el nombre
de la matriz que queremos conocer al fnal de la URL, por ejemplo:
http://www.php.net/_server
A continuación, veremos un cuadro con los nombres de estas matrices defnidas por
el intérprete de PHP:
Muchos de los valores de estas matrices no están disponibles en todos los servi-
dores, ya que dependen de que el administrador del servidor haya habilitado su uso, por lo
cual no es posible hacer una lista completa que esté disponible bajo todas las circunstancias.
Habrá que probar en cada servidor antes de utilizar un dato proveniente de estas matrices.
Notemos que todos los nombres de estas matrices –salvo uno– comienzan con guión
bajo, y que todas estas matrices defnidas por el intérprete de PHP llevan escrito su nombre
completamente en mayúsculas, tal como si fueran una constante; eso permite que poda-
mos diferenciarlas fácilmente dentro de nuestro código de las otras matrices que nosotros
mismos hayamos declarado.
Será muy común de ahora en más que utilicemos en nuestros códigos datos obteni-
dos a partir de estas matrices defnidas automáticamente por el intérprete de PHP. Ya en el
siguiente capítulo comenzaremos a utilizar varias de estas matrices.
Y con esto damos por terminada esta introducción a los almacenes de datos proviso-
rios que más utilizaremos en PHP: variables, constantes y matrices. Seguiremos profundi-
zando más detalles y aplicando reiteradamente estos almacenes de datos en los siguientes
capítulos, así como también aprenderemos a interactuar con los restantes almacenes de
datos más perdurables.
desde nuestra computadora hacia el hosting, y estos datos son remitidos en la forma de
variables, de dos maneras:
1 . mediante enlaces especiales
2. y mediante formularios.
A continuación, analizaremos ambas posibilidades, puesto que el envío de datos desde
el navegador de un usuario hacia el servidor, constituye un giro fundamentalmente interactivo,
que deja en manos de cada usuario los contenidos (dinámicos) que recibirá como respuesta
del servidor.
Es importante que observemos que dentro del valor del atributo href, luego de espe-
cifcar la URL solicitada (la página recibe.php), se ha agregado un signo de pregunta: ? Este
signo indica que, a continuación, enviaremos una o más variables hacia el servidor Web.
La sintaxis para enviar una variable consiste en colocar primero su nombre; luego, un
signo igual; después, su valor de defnición.
<p>
<a href="destino.php?nombre=Pepe">Este
es el enlace de Pepe</a><br />
<a href="destino.php?nombre=Pedro">Este
es el enlace de Pedro</a><br />
<a href="destino.php?nombre=Juan">Este es el enlace de
Juan</a>
</p>
Una vez que nuestro navegador visualiza esa página, según cuál de los enlaces pulse-
mos, enviaremos hacia el servidor un valor distinto para la variable nombre. Siempre man-
daremos la misma variable, pero con distinta información almacenada dentro de ella. Y, cabe
señalar, que sólo remitiremos uno de los valores posibles (no existe un mouse que nos permita
pulsar simultáneamente más de un enlace).
En el archivo destino.php daremos por sentado que llegó esa variable, por esta razón,
escribiremos la orden print dentro del código HTML, que solicitará al intérprete de PHP que
escriba el valor de la variable denominada nombre.
Para eso, usaremos esta sintaxis:
Por supuesto, a esta página le falta la DTD y la apertura de las etiquetas html, head,
body, etc., y su correspondiente cierre, que deberemos agregarlo al fnal.
<p>
<a href="datos.php?nombre=Pepe&apellido=Perez&edad=17">Este
es el enlace de Pepe</a><br />
<a href="datos.php?nombre=Pedro&apellido=Garcia&edad=9">Es
te es el enlace de Pedro</a><br />
<a href="datos.php?nombre=Juan&apellido=Fernandez&edad=30">
Este es el enlace de Juan</a>
</p>
Ese código enviará hacia el servidor tres variables: nombre, apellido y edad.
Nota importante: si este código se incluye dentro de un documento XHTML Strict,
deberemos codifcar el ampersand con su respectiva entidad HTML, de esta manera:
&
Por lo tanto, cada enlace será similar a éste:
<a href="datos.php?nombre=Pedro&apellido=Garcia&ed
ad=9">Este es el enlace de Pedro</a><br />
<?php
print ("<p>Los valores fueron: " ) ;
print ("<br />");
print ($_GET["nombre"]);
print ("<br />");
print ($_GET["apellido"]);
print ("<br />");
print ($_GET["edad"]);
print ("</p>");
?>
Notemos al pasar que hemos ordenado al intérprete de PHP escribir, entre un dato y
otro, un salto de línea o break (<br />), para que los valores queden claramente uno en cada
línea, y no todos a continuación en un mismo renglón. Una variante de este envío de variables,
mediante el método get, es experimentar su paso directamente desde el navegador, escri-
biendo sus nombres y sus valores en la barra de direcciones de nuestro navegador; esto
es muy práctico para probar qué valores están llegando a la siguiente página rápidamente,
sin tener que crear una página con un enlace específco para probarlo. A menudo utilizaremos
esta técnica para detectar errores mientras programamos, si sospechamos que no llega al
servidor el dato que esperamos.
Escribir eso dentro de la barra de direcciones del navegador, equivale a colocar dentro
de un enlace el atributo href con este valor:
http://localhost/recibe.php?nombre=Pepe&apellido=Perez&
amp;edad=17
Cuando pulsemos Enter esto se enviará al servidor y se logrará un efecto idéntico a los
enlaces anteriores, puesto que pulsar un enlace o escribir algo en la barra de direcciones de
un navegador logra el mismo efecto: en ambos casos, el navegador realiza una petición del
protocolo HTTP, que utiliza el método get para adjuntar las variables.
Formularios
Otro método para enviar variables hacia el servidor es el típico formulario de ingreso de da-
tos, en el que una persona escribe algo en su navegador, mientras visualiza el formulario en
su pantalla. Luego se enviarán esos datos hacia el servidor para que se realice con ellos algu-
na operación (por ejemplo: enviar los datos a una base, o por correo electrónico, o utilizarlos
para construir una página dinámica que se mostrará a continuación).
Un formulario consiste en una simple etiqueta del lenguaje HTML denominada <form>,
por lo que no es preciso que la página en la que se incluye el formulario lleve extensión .php,
sino que puede ser un archivo .html normal (aunque la extensión .php tiene ciertas ventajas
que apreciaremos más adelante, cuando aprendamos a validar los datos ingresados en un
formulario).
Los elementos principales de un formulario (además de la etiqueta <form>) son los
siguientes:
1. El atributo action, que indica a qué página de destino se envían las variables. Ade-
más, es ésa la página que se nos mostrará cuando pulsemos en el botón Enviar,
tal como si hubiésemos pulsado un enlace hacia esa página. Siempre apuntare-
mos hacia una página con extensión .php, para poder leer los datos enviados por
el formulario.
2. El atributo method, que especifca uno de los dos posibles métodos o formas de
enviar las variables hacia el servidor: a la vista de todos, en la URL del navegador
(method=“get”), o de manera oculta, invisible en la URL (method=“post”). Este
último método es el más utilizado en formularios, y es el que recomendamos.
3. Algún campo o control de formulario (campo de texto, menú de selección, botón
de tipo radio, casilla de selección, etc.), que permita al usuario el ingreso o la selec-
ción de datos. Lo fundamental de cada campo será su nombre (atributo name),
ya que ése será el de la variable que estará disponible en la página de destino.
4. Un botón (un campo input de tipo submit) para enviar los datos.
Esos son los elementos mínimos con los que debe contar un formulario para que pueda
enviar datos hacia el servidor.
Veamos un ejemplo de todos estos elementos aplicados en la creación de un archivo al
que llamaremos formulario.html:
Y ahora realizaremos muestra.php, que es la página que recibirá la variable que contiene
lo que haya escrito el usuario en el formulario, y la mostrará (obviamente, falta agregar la DTD
y las etiquetas estructurales básicas):
<?php
print ("Su dirección e s : " ) ;
print ($_POST["domicilio"]);
?>
Esperamos a que llegue una variable llamada domicilio a esta página, y notemos que,
como fue enviada al servidor mediante un formulario que especifcaba el método post, el
intérprete de PHP acomodó esa variable dentro de la matriz $_POST, por eso tenemos que
leer el dato de una celda de esa matriz, para ser precisos, de la celda $_POST[“domicilio”].
Cada control de formulario de tipo input nos generará una variable que se enviará
hacia el servidor, por lo cual, si quisiéramos que el usuario escriba varios datos, sólo tendre-
mos que agregar varios inputs, de cualquier tipo (campo de texto, área de texto, menú de
selección, botones tipo radio, casillas de selección, etc.).
Recomendamos repasar algún manual o tutorial de HTML para recordar cuáles son
todos los elementos (tipos de controles) posibles de un formulario.
En los capítulos siguientes, aprenderemos a validar los datos esperados, y aplicaremos
un manejo bastante más avanzado de los formularios que el que nos ofrece HTML.
http://www.google.com.ar/search?q=palabra
login.php?usuario=pepe&password=secreto
Esto produciría un serio problema de seguridad a nuestros usuarios si, por ejemplo,
acceden desde una computadora compartida (cibercafé, trabajo, etc.), puesto que otros
usuarios podrían visitar el enlace desde el historial del navegador, y entrar donde no deben.
La conclusión es que no debemos enviar datos importantes mediante peticiones
que usen el método get. Pero sí podemos usarlos para enviar datos de “navegación”, como
códigos de categorías, de productos, palabras a buscar, etc.
Para esta tarea tan común de verifcación de datos antes de utilizarlos, se usan los
condicionales, que es el tema que aprenderemos a continuación.
Los condicionales
If (si...)
Muchas veces querremos que nuestro código sea capaz de decidir automáticamente si
se ejecuta un bloque de código, o no, dependiendo de algo que haya sucedido (la condición
que se evaluará puede ser algo que haya sucedido con los datos que vienen del usuario, que
él haya hecho clic en una opción o en otra, que una variable tenga un valor, o no, que se haya
llegado a la página mediante un método u otro, etc.).
Algunos ejemplos: si la contraseña enviada por el usuario es igual a la que está defnida
dentro de nuestro código, le mostramos un contenido especial. Si es viernes, mostramos una
frase deseando un buen f n de semana. Si el usuario eligió ver la categoría “A” de productos,
le mostramos el listado únicamente de esos productos y no de otros.
Continuamente nos encontramos con este tipo de situaciones en la vida real, por ejem-
plo: “si está lloviendo, llevo el paraguas”; “si es de noche, enciendo una lámpara”. Es una
cuestión de simple lógica.
Para proveer a nuestro código la capacidad de “evaluación de las circunstancias” y su
posterior decisión automatizada, en PHP disponemos del condicional if, que nos permite
evaluar si una circunstancia es “verdadera”, si está sucediendo y, según el resultado de esa
evaluación, nos permite ejecutar un bloque de código.
Es decir: podemos hacer que la ejecución de un bloque de código sea condicional (de
allí el nombre), que sólo en el caso de que la condición planteada sea verdadera, se ejecute;
en caso contrario, no sucederá nada, se continuará ejecutando el código siguiente a ese
condicional.
La estructura del if puede tener algunas variantes, la más simple de todas es la que
sigue:
if (condición a evaluar) {
Bloque que se ejecuta sólo si esa condición resulta
ser verdadera
}
if (llueve) {
Llevar el paraguas
}
Esto signifca que esas acciones envueltas entre las llaves del condicional, no siempre
se realizarán (¡no salimos todos los días con el paraguas!), sino que esos bloques de código
sólo se ejecutarán cuando la condición que se evaluará sea verdadera (que llueva, en este
caso). De lo contrario, se seguirán ejecutando las órdenes que sigan a continuación.
Veamos un ejemplo en PHP:
<?php
if ($_POST["password"]== "superagente86") {
echo "<h1>Maxwell, atienda el zapatófono que lo
estamos llamando de Control</h1>";
}
?>
En este ejemplo, damos por hecho que desde otra página hemos enviado, mediante un
formulario con method=“post”, un input llamado password. Solamente si dentro de ese cam-
po hemos enviado el dato “superagente86”, la condición será verdadera, y el echo escribirá
el mensaje dentro de la página.
En caso contrario (que el usuario haya escrito cualquier otro texto), la condición será
evaluada como falsa, y el bloque de código envuelto entre las llaves del if no se ejecutará, por
lo tanto, el echo no escribirá nada. Ese echo, el código envuelto entre las llaves del if, es un
if (condición a evaluar) {
Bloque que se ejecuta sólo si la condición resulta
ser verdadera
} else {
Bloque que se ejecuta sólo si la condición es falsa
}
Una conclusión fundamental es que jamás se ejecutan ambos bloques en una mis-
ma ocasión. O se ejecuta el bloque inicial, el que está envuelto entre las llaves del if, o
el bloque envuelto por las llaves del else, pero nunca ambos. O un bloque, o el otro. Es
excluyente.
Esto es así porque la condición del if no puede ser verdadera y falsa a la vez, en un
mismo momento. O es verdadera, o es falsa.
Si la condición es verdadera, se ejecuta el bloque de órdenes que está encerrado entre
las primeras llaves, las del if, y no el bloque del else.
Si, en cambio, la condición es falsa, no se ejecuta el bloque del if, y sólo se ejecuta el
bloque delimitado entre las llaves del else. O uno, o el otro.
<?php
if ($clima == "lluvia") {
echo "Llevar paraguas";
} else {
echo "No llevar paraguas";
}
?>
Por supuesto, para que esto funcione, démosle previamente un valor a $clima, y probe-
mos de cambiarlo; que a veces sea “lluvia”, así vemos cómo se ejecuta el bloque verdadero,
y que a veces sea otra cosa, así se ejecuta el bloque del else.
Para mayor claridad, a los bloques de instrucciones que hay que ejecutar –lo que
está dentro de las llaves del if o del else–, les dejamos un tabulador, o 3 o 4 espacios
de sangría a su izquierda, para facilitar su lectura.
Veamos otro caso real. Vamos a hacer un código bien “educado”, que salude a las
personas según su sexo.
Crearemos el archivo elegir.html, que consta del siguiente formulario (por supuesto,
agregaremos la DTD, etiquetas html, head, body, etc.):
Por otro lado, recibimos el valor de la variable “sexo” en el archivo denominado saludar.
php, y según lo que haya elegido el usuario, le mostraremos uno u otro saludo:
Código de saludar.php:
<?php
if ($_POST["sexo"] == "masculino"){
print ("¡Hola hombre!");
} else {
print ("¡Hola mujer!");
}
?>
<?php
if ($_POST["edad"] < 18){
print ("¡Hola niño!");
} elseif ($_POST["edad"] < 30){
print ("¡Hola joven!");
} elseif ($_POST["edad"] > 29){
print ("¡Hola adulto!");
}
?>
Hemos creado tres condiciones excluyentes (que pudieron ser muchas más).
Veamos otro ejemplo: esta vez, de una sucesión de un if inicial, un elseif, y un else fnal:
<?php
if ($_POST["sexo"] == "masculino"){
print ("¡Hola Hombre!");
Como podemos observar, el elseif no sólo cierra el if anterior, sino que abre uno nuevo
y plantea una nueva condición, distinta, independiente de la anterior, pero con la parti-
cularidad de que será evaluada solamente en el caso de que la anterior condición hubiera
resultado ser falsa. De lo contrario, si la anterior condición era verdadera, el programa ni se
toma el trabajo de evaluar esta segunda condición... salta directamente hasta después de la
llave de cierre del if, sin evaluar ninguna condición más.
De esta forma, pueden encadenarse muchas alternativas que requieran, para ser eva-
luadas, que una condición anterior hubiese resultado falsa.
Un dato muy interesante es que las condiciones sucesivas no tienen por qué evaluar
el valor de una misma variable, lo cual nos da la libertad de ir evaluando distintas cosas en
cada condición:
<?php
if ($_POST["sexo"] == "masculino"){
print ("¡Hola Hombre!");
} elseif ($_POST["estado"] == "soltera"){
print ("¡Hola Mujer soltera!");
} elseif ($_POST["edad"] > 70){
print ("¡Hola abuela!");
}
?>
En este caso, como son dos las posibles respuestas de la primera condición, pudimos
plantear una segunda condición que no vuelva a evaluar otra vez la misma variable “sexo”,
sino que evalúa otra cosa, en este caso, “estado”. Y, luego, plantearemos otra condición con
la “edad”, sólo en el caso de que la anterior condición no se hubiese ejecutado. Es impor-
tante tener en claro que solamente en el caso de que haya sido falsa la condición anterior, se
ejecuta la siguiente. Si una de las condiciones es verdadera, ya no se ejecuta el resto de las
condiciones.
En el caso de tener más de dos posibilidades que evalúan el valor de una misma va-
riable, veremos que es mucho más práctico aplicar una estructura diferente, que es la del
switch y los case. Veamos un ejemplo:
<?php
if ($dia == "lunes"){
print ("¡Feliz día de la Luna!");
} elseif ($dia == "martes"){
print ("¡Feliz día de Marte!");
} elseif ($dia == "miércoles"){
print ("¡Feliz día de Mercurio!");
} elseif ($dia == "jueves"){
print ("¡Feliz día de Júpiter!"
} elseif ($dia == "viernes"){
print ("¡Feliz día de Venus!");
} elseif ($dia == "sábado"){
print ("¡Feliz día de Saturno!"
} elseif ($dia == "domingo"){
print ("¡Feliz día del Sol!");
}
?>
En este caso, en el que evaluamos una serie de valores posibles de una única variable,
es mucho más breve y simple utilizar una estructura selectiva, como el switch, que aprende-
remos a usar a continuación.
<?php
switch ($dia){
// aquí evaluaremos los posibles valores de $dia
}?>
<?php
switch ($dia){
case "lunes":
$texto = "¡Feliz día de la Luna!";
break;
case "martes":
$texto = "¡Feliz día de Marte!";
break;
case "miércoles":
$texto = "¡Feliz día de Mercurio!";
break;
case "jueves":
$texto = "¡Feliz día de Júpiter!";
break;
case "viernes":
$texto = "¡Feliz día de Venus!";
break;
case "sábado":
$texto = "¡Feliz día de Saturno!";
break;
case "domingo":
$texto = "¡Feliz día del Sol!";
break;
}
print ($texto);
?>
Como vemos, esta estructura solamente nos sirve en caso de que conozcamos las po-
sibles alternativas excluyentes (todos los valores posibles de la variable que se evaluará).
Los case del ejemplo anterior no tienen prevista ninguna acción para el caso en que
$dia tenga un valor distinto a los siete valores defnidos.
Para evitar el riesgo de este “vacío” lógico, se utiliza en el último lugar de la sucesión
de case, mejor dicho, después del último case, la expresión default (por defecto). El código
envuelto en ese bloque, se ejecutará en cualquier otro caso en que la variable evaluada
contenga cualquier otra cosa no prevista en ninguno de los case anteriores:
<?php
switch ($dia){
case "lunes":
$texto = "¡Feliz día de la Luna!";
break;
case "martes":
$texto = "¡Feliz día de Marte!";
break;
case "miércoles":
$texto = "¡Feliz día de Mercurio!";
break;
case "jueves":
$texto = "¡Feliz día de Júpiter!";
break;
case "viernes":
$texto = "¡Feliz día de Venus!";
break;
case "sábado":
$texto = "¡Feliz día de Saturno!";
break;
case "domingo":
$texto = "¡Feliz día del Sol!";
break;
default:
$texto = "¡Feliz día fuera de calendario!";
break;
}
print ($texto);
Podemos probar cargando distintos valores dentro de la variable $dia para ver cómo se
ejecuta uno u otro case, o el default.
== Igual a $x = = $y $x es igual a $y
!= Distinto de $x != $y $x es distinto de $y
<?php
if ($_POST["edad"] < 18){
print ("Es menor a 18 años");
}
Si queremos saber si algo es distinto a otra cosa, también tenemos dos maneras de
compararlo: con el operador <> o con !=:
<?php
if ($_POST["nombre"] != "Pepe"){
?>
Operadores lógicos:
En otros casos, necesitaremos crear condiciones complejas, que requieran combinar (unir)
dos o más condiciones simples en una, para evaluarlas como una sola condición. Al ele-
mento que permite combinarlas lo llamamos operador lógico.
Veamos un ejemplo simple aún sin entrar en detalles, para tratar de comprender el con-
cepto. Supongamos que tenemos que averiguar si la edad de un usuario está entre 18 y 65
años para mostrarle un texto especial. Tienen que cumplirse dos condiciones: la primera es
que su edad sea mayor a 17 (o “mayor o igual” a 18), y la segunda es que su edad sea menor
a 66 (o “menor o igual” a 65):
Para evaluar con un solo condicional estas dos condiciones, necesitamos “unirlas”, y
convertirlas en una sola condición que sea evaluada como verdadera (si es mayor a 17 y,
además, menor a 66) o falsa, en caso contrario. Eso que se usa para unir las dos condiciones
en una sola, es lo que denominamos un operador lógico. En este ejemplo, el operador ne-
cesario es and (signifca y, que es el nombre del operador de conjunción). Para que devuelva
verdadera la expresión completa, necesitamos que sea verdadera la primera condición y que
además sea verdadera la segunda.
En este caso, le pediríamos que ingrese la edad en un campo de texto (suponga-
mos que el name de esa campo sea “edad”) y la evaluaríamos de la siguiente manera
(de paso, observemos que hemos redactado cada condición con otros operadores de
comparación que en el caso anterior, esta vez usando >= y <= y modifcando el valor que
se comparará).
} else {
print ("Fuera del rango");
}
Notemos que combinamos dos condiciones completas en una sola, incluso cada una
de ellas podría haberse colocado por separado, en un if distinto, individualmente:
$_POST["edad"] >= 18
y
$_POST["edad"] <= 65
Lo único que hemos hecho es unirlas con el operador and. Por supuesto, podemos
unir más de dos condiciones, usando un mismo operador o distintos. Imaginemos que ne-
cesitamos evaluar si la edad es mayor a 17 y menor a 66, o el estado civil es “viudo”; las tres
condiciones por separado serían:
$_POST["edad"] >= 18
y
$_POST["edad"] <= 65
o
$_POST["estado"] == "viudo"
En este caso, primero se evaluarían las condiciones unidas mediante el operador and
(que sea mayor a 17 y menor a 66) y si eso es verdad, ya es sufciente para que toda la expre-
sión se considere verdadera. Del mismo modo, si esa primera parte fue falsa, pero el estado
era “viudo”, al estar unidas por el operador or, devuelve verdadero, ya que ese operador
necesita que al menos una de las condiciones sea cierta, sin importar si otras no lo son. Po-
demos unir cualquier cantidad de condiciones, variando los operadores libremente y creando
una única condición que será evaluada en conjunto.
Tablas de verdad:
Todos los operadores lógicos evalúan el “valor de verdad” (es decir, si es verdadera o falsa)
de cada una de las condiciones por separado y, luego, según el operador utilizado para unir
estas condiciones, devuelven un único valor de verdadero o falso para el conjunto completo
de condiciones que formaban esa expresión.
Vamos a analizar cuatro operadores lógicos:
• and (conjunción, también puede escribirse en PHP como &&),
• or (disyunción, también puede escribirse en PHP como ||),
• xor (disyunción excluyente, informalmente llamado “or excluyente”),
• ! (negación).
Si a las dos condiciones que uniremos mediante operadores lógicos les damos un
nombre simbólico y las denominamos $x e $y, los valores de verdad pueden ser solamente
cuatro:
• que ambas condiciones sean verdaderas,
$x $y
V V
F F
V F
F V
$x $y $x and $y
V V V
V F F
F V F
F F F
$usuario = "pepe";
$clave = 123456;
} else {
print ("No lo conocemos, disculpe pero queda fuera");
}
$usuario = "juan";
$clave = 123456;
En este caso, se evaluaría como falsa la condición, ya que la primera condición (que
$nombre valga “pepe”) se evalúa como falsa, así que, por más que la segunda sea verdadera,
al haber unido a ambas con un operador de conjunción and, la condición entera se evalúa
como falsa.
Del mismo modo, podríamos volver a cambiar los valores de esas dos variables, esta
vez a algo como:
$usuario = "pepe";
$clave = 99999;
Y también en este caso, se evaluaría como falsa la condición, ya que la primera condi-
ción es verdadera, pero la segunda es falsa.
Desde ya que también se evaluaría como falsa si ambas partes fueran falsas (tanto el
nombre como la clave).
Disyunción:
$x $y $x or $y
V V V
V F V
F V V
F F F
La única forma de que una disyunción resulte falsa es que todas las condiciones sean
falsas, sin excepción.
Veamos un ejemplo con PHP. Imaginemos que un sitio de comercio electrónico realiza
envíos a domicilio solamente en tres ciudades: Ciudad 1 , Ciudad 2 y Ciudad 3; solicitamos al
usuario que ingrese su ciudad de residencia en un campo llamado “ciudad”, y evaluamos ese
dato. Necesitamos que al menos uno de esos tres nombres de ciudad sea el que verdade-
ramente ingresó el usuario para dar por verdadera la condición entera, y realizar el pedido.
Entonces, usaremos un operador de disyunción:
} else {
print ("Está fuera del área de cobertura.");
}
$x $y $x xor $y
V V F
V F V
F V V
F F F
$tarjeta = "VISA";
$cupon = 19876;
Y que queremos validarlos con la regla de que si paga con tarjeta VISA, no se conside-
rará ningún cupón de descuento. Por el contrario, si ingresa un cupón de descuento, la forma
de pago no puede ser VISA. Son excluyentes:
} else {
Negación:
$x !$x
V F
F V
if ($_POST["nombre"] != "Pepe"{
Tipos de validaciones
¿Está presente cada dato requerido?
En este “diálogo en etapas” que implican las páginas dinámicas, este “estar esperando” en
una segunda página un dato que el usuario debería haber enviado hacia el servidor desde una
página anterior (ya sea con un enlace que envía variables, o con un formulario), puede suceder
que el dato esperado nunca llegue, con lo cual se frustraría el intento de usarlo.
Volvamos a analizar el código de un ejemplo anterior: supongamos que tenemos una
página llamada formulario.html que contiene esto:
Y también tenemos una página llamada muestra.php, que es la página en la que esta-
remos esperando la variable “domicilio”, para usarla:
<?php
print ("Su direccion e s : " ) ;
print ($_POST["domicilio"]);
?>
Este esquema está dando por supuesta una situación ideal, una forma esperada de
navegar por estas dos páginas, que no necesariamente será el camino que seguirá todo
usuario. Damos por supuesto lo siguiente:
1. que el usuario ingresará primero a formulario.html,
Su domicilio e s :
Notice: Undefned index: domicilio in... etc.
<?php
if ( isset($_POST["domicilio"]) ){
<?php
if ( isset($_POST["nombre"],$_POST["apellido"],$_POST["edad"])
){
// Sólo si todos esos datos están presentes, devuelve
verdadero y se ejecuta lo que esté entre las llaves del if
}
<?php
if ( isset($_POST["nombre"]) and isset($_POST["apellido"]) and
isset($_POST["edad"]) ){
// sólo si todos esos datos están presentes, devuelve
verdadero y se ejecuta lo que esté entre las llaves del if
}
Si no está vacío
Otra posibilidad diferente (aunque parecería ser igual a la anterior, no lo es) es que el usuario
sí pase por el formulario, pero lo envíe hacia el servidor sin haber escrito nada dentro del
campo. Es decir, el dato esperado sí estará “defnido”, habrá llegado al servidor, pero con un
valor de “nada”, totalmente vacío.
La diferencia entre “estar defnido” y “estar vacío” es similar a la diferencia entre el hecho
de que haya llegado una carta a nuestro buzón de correo, y que la carta esté vacía.
• El no estar defnida una variable equivale a que no nos llegó ninguna carta.
• Estar defnida equivale a que llegó la carta (pero todavía puede ser que esté llena
o vacía, hasta que no la abramos no lo sabremos).
• Estar vacía da por sentado que llegó (está defnida), pero sin contenido.
• Estar llena es la situación ideal: llegó (está defnida) y tiene contenido (no está
vacía).
Validar esta posibilidad es posible mediante los operadores de comparación que he-
mos utilizado en otras ocasiones. Según la forma en que expresemos la condición, podemos
utilizar distintos operadores de comparación. Podemos querer saber si algo está vacío, y en
ese caso escribiríamos así la condición:
<?php
if ($_POST["domicilio"] == ""){
// si es cierto, es que está vacío
Y, en otros casos, si queremos saber si algo no está vacío, podemos usar tanto el
operador <> como el operador !=, cualquiera de los dos:
<?php
i f ($_POST["domicilio"] <> " " ) {
/ / s i e s c i e r t o , e s q u e NO está vacío
}
?>
O lo que es igual:
Notemos que hemos utilizado el operador de negación ! para que la condición sea ver-
dadera si “no es igual” a vacío (y expresamos el valor vacío mediante “nada” entre comillas,
literalmente nada, ni siquiera un espacio vacío entre la apertura y el cierre de las comillas).
De esta manera, sabremos si un dato ha sido llenado con algún valor por el usuario
antes de utilizarlo en nuestro código.
Aplicado al ejemplo anterior, podríamos combinar ambas validaciones en una sola (que
esté presente el dato, y que no esté vacío) mediante un operador lógico que una ambas
condiciones:
<?php
$mes = 1 0 ; // supongamos que esto llegaría desde un
formulario
} else {
Es importante que observemos cómo hemos usado el operador lógico and para de-
fnir un rango mediante la unión de dos condiciones diferentes: que $mes sea mayor a cero
(primera condición), y que $mes sea menor o igual a 12 (segunda condición). Con esos dos
límites, tenemos defnido un rango de valores permitido. Si ambas condiciones son ciertas,
se ejecuta el código envuelto entre las llaves del if; en caso contrario, se ejecuta lo envuelto
entre las llaves del else.
Si en vez de un único rango, se tratara de una serie de rangos de valores, deberíamos
utilizar una serie de elseifs:
<?php
$total = 1 4 5 ; // supongamos que esto llegaría desde un
formulario
}
} else {
}
?>
Figura 7-1. El servidor Web le pide al navegador que cree una cookie.
dor todos estos datos en cada “petición” que el usuario realice hacia ese mismo dominio (es
decir, en cada enlace que pulse o en cada formulario que lleve hacia una página de ese sitio
que le ordenó crear la cookie).
De esa manera, ese servidor podrá identifcar a ese usuario a lo largo de su nave-
gación por las distintas páginas de ese mismo sitio, algo que le servirá tanto para mostrarle
contenidos específcos creados para ese usuario, como para otras tareas más invisibles para
el usuario pero muy útiles para el dueño del sitio como, por ejemplo, llevar estadísticas de las
visitas de cada usuario.
Algunos usos posibles: el servidor puede almacenar el nombre del usuario para saludar-
lo cada vez que entre a una página de ese sitio; memorizar los productos que lleva elegidos
de un carrito de compras hasta que complete la operación de compra; recordar el idioma
preferido por el usuario para navegar por ese sitio; o la fecha de su última visita. Y muchísimos
otros usos más.
La forma en que un servidor Web (típicamente Apache, el servidor Web instalado en la
mayoría de los hostings) le ordenará al navegador del usuario (Firefox, Explorer, Opera, etc.)
que cree alguno de esos archivos de texto denominados cookies, estará totalmente bajo
nuestro control, ya que será nuestro propio código PHP el que le ordenará al servidor Web
que éste, a su vez, le solicite al navegador la creación de la cookie y, una vez creada, otro
código PHP será capaz de solicitar que se almacenen datos dentro de ese archivo, o que se
lean los que allí fueron guardados.
La manera en que estos archivos de texto se crean en el disco rígido del usuario no
debe preocuparnos: de eso se encarga el navegador del usuario, luego de que ejecutemos
la instrucción de PHP que, en unos instantes, aprenderemos.
la petición HTTP que nos trae el archivo HTML, desde el servidor hacia el navegador; por lo
que la ejecución de la función que crea un archivo de cookies debe ser anterior a cualquier
código HTML o a cualquier echo de PHP que haya en la página (igual que con las sesio-
nes, como veremos pronto), para que llegue dentro de los encabezados de la petición HTTP.
En el siguiente ejemplo veremos cuál sería la ubicación del código que crea una cookie:
<?php
setcookie("nombre","Juancito");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html ...etc...
</html>
setcookie("nombre","Juancito");
La función setcookie permite especifcar varios otros argumentos dentro de sus parén-
tesis, pero son todos opcionales:
Algunos de ellos los veremos unos párrafos más adelante. Pero con esos dos datos
(el nombre de la variable y su valor), separados por comas y envueltos entre comillas, es
sufciente para crear una cookie y guardar un dato.
Este ejemplo, que defne una variable denominada “nombre” con el valor “Juancito”, ha
creado realmente una cookie (probemos de ejecutarlo en nuestro servidor local, o en nuestro
hosting). Como no se ve nada especial en la pantalla, nos queda la duda: no sabemos si se
ha logrado crear esta cookie, o no...
Afortunadamente, es muy fácil comprobar si se creó, o no: podemos ver con nuestro
propio navegador todas las cookies que ese navegador ha almacenado, y cuál es el valor que
guarda dentro cada una de ellas.
En cada navegador es diferente la forma de acceder a las cookies; por ejemplo, en
Firefox, accedemos entrando al menú Herramientas Opciones Privacidad
Eliminar cookies de forma individual, que nos muestra el listado de cookies que exis-
ten en ese navegador, así como su contenido, su fecha de expiración y otras informaciones
complementarias.
En este caso, se vería de esta manera:
De esta forma, verifcamos si la cookie fue creada y con qué valor. Esto es muy útil
mientras programamos y necesitamos detectar si funcionó nuestro código o si hubo errores.
Pero por supuesto, la forma más usual de trabajar con los datos guardados en las cookies es
la de leerlos y utilizarlos directamente desde los códigos PHP que programemos en nuestras
páginas y que aprenderemos a continuación.
Vamos a tratar de entender cómo es el circuito de lectura de un dato que estaba en una
cookie. Como dijimos, la cookie es reenviada automáticamente por el navegador hacia el
servidor (hosting) cada vez que el navegador detecta que se está realizando una petición a
una URL de un dominio que ya tiene almacenada una cookie en ese mismo navegador. Es
decir, en cuanto pulsamos un enlace, despachamos un formulario o escribimos una
URL y pulsamos enter, si cualquiera de estas tres acciones apunta hacia un sitio que an-
teriormente nos guardó una cookie, en ese mismo instante, nuestro navegador envía hacia
el servidor las variables contenidas en la cookie correspondiente a ese sitio (las vaya a
usar o no ese servidor, que no es cuestión que le interese al navegador, él sólo las envía sin
preguntar), sin necesidad de que tengamos que hacer nada especial, todo sucede de forma
invisible y automática.
<?php
setcookie("mivariable", "datos, datos y más datos", time()+60);
// Recordemos que esto es imprescindible que esté al inicio del
archivo
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
...etc...
</head>
<body>
<h1>¡Ya se creó la cookie!</h1>
</body>
</html>
Mediante este código, defnimos en la máquina del usuario una variable denominada
“mivariable”, en la que guardamos un texto que dice “datos, datos y más datos”.
El tercer argumento de la función setcookie especifca la duración o el momento de
vencimiento de la cookie; es decir, cuándo el navegador del usuario deberá eliminar el
archivo de texto de su disco rígido. En este caso, se ha pasado como tercer argumento el
instante actual (la función time(), tema que veremos más adelante en este libro) más 60 se-
gundos, esto signifca que luego de un minuto se autodestruirá esa cookie. Si la intentamos
leer pasados los 60 segundos, no estará disponible el dato, ya no existirá (si no especifcamos
ningún momento de borrado, la cookie se eliminará automáticamente en cuanto el usuario
cierre su navegador).
Si lo queremos probar luego de ejecutar una vez el código que crea la cookie, ingrese-
mos con nuestro navegador en otra página de nuestro mismo servidor que contenga una
lectura de esa variable, podríamos llamarla otra-pagina.php, y contendría algo así:
} else {
}
?>
</h1>
</body>
</html>
Si en lugar de hacer en dos páginas diferentes este uso de datos de cookies, quisié-
ramos hacerlo en una sola página, el código sería similar al siguiente (podemos llamar a esta
página en-una-sola.php):
<?php
if (!isset($_COOKIE["mivariable"])) {
// Si NO está presente, la creamos:
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
...etc...
</head>
<body>
<h1>
<?php
if ( isset($_COOKIE["mivariable"]) ) {
// Si está disponible, la usamos:
} else {
}
?>
</h1>
</body>
</html>
No es lo mismo eliminar el archivo de cookie completamente del disco del usuario, que sim-
plemente vaciar el valor de alguna de sus variables.
La forma de vaciar el valor de una variable de una cookie es muy simple, y consiste en
defnirla tal como si la estuviéramos creando, pero sin especifcarle ningún valor:
De todos los parámetros posibles que podemos proporcionar dentro de los paréntesis
al crear una cookie, el único obligatorio es el nombre de la variable y, en el caso de ser el
único que proporcionemos, produce el vaciamiento de los datos que hubiéramos almace-
nado con anterioridad en esa variable.
Con la misma lógica que en el caso de crear una cookie, si luego de ordenar borrar
una cookie, en el mismo código de la misma página que se está ejecutando en el servidor
intentamos leer esa cookie, ésta todavía existirá, ya que recién en la siguiente petición al
servidor dejará de estar disponible su dato.
Esto no solo vacía el valor de la variable, sino que elimina la variable misma.
En cambio, para eliminar por completo el archivo de la cookie del disco del usuario,
será necesario utilizar un argumento extra de la función setcookie, que aprenderemos a
continuación.
Argumentos opcionales
Ya hemos utilizado en los distintos ejemplos varios de los argumentos o parámetros que po-
demos utilizar dentro de los paréntesis de la función setcookie.
La totalidad de estos argumentos es la siguiente:
El cuarto argumento de la función que crea una cookie, la ruta, indica desde qué
directorio (carpeta) de un servidor se accederá a los datos de esa cookie, impidiendo la
lectura de sus datos a toda página PHP que no esté almacenada dentro de esa carpeta.
Un ejemplo:
<?php
setcookie("prueba",$valor,time()+3600,"/foro/","",1);
?>
Otro ejemplo:
<?php
setcookie("ingreso",$datos,time()+(60 * 60 * 24),"","ar.
En este caso, la cookie tendrá una duración de 24 horas, y solamente se podrá leer
desde cualquier carpeta del subdominio ar dentro del dominio undominio.com que se es-
pecifcó, sin que sea necesaria una conexión segura para enviar los datos.
Y, por último, si queremos eliminar una cookie por completo, vaciando el valor de
su variable y eliminando físicamente el archivo del disco del usuario, la forma de hacerlo es
indicando un momento de vencimiento anterior al actual (en el siguiente ejemplo, el “cero” del
tercer argumento):
Tengamos presente, entonces, que existen tres herramientas distintas para “eliminar”
datos relacionados con las cookies, pero que no son iguales:
1. Vaciar una variable de cookie sin eliminarla, con setcookie sin valor.
2. Eliminar del servidor una variable ya leída con unset.
3. Eliminar el archivo físico del disco del usuario con setcookie y fecha anterior.
Ejemplo completo
Veamos ahora un ejemplo algo más complejo, pero completo y listo para usar, de uso de
cookies para generar código HTML personalizado.
En este caso, el objetivo será generar apenas una palabra que se escribirá con un
echo de PHP dentro de la etiqueta <link> de las páginas de nuestro sitio:
Por lo cual, según el valor de esa palabra, será una hoja de estilos distinta la que el
navegador aplicará para ese usuario durante su navegación a través de ese sitio (que permita
ofrecer algunas opciones de diseño personalizado a cada usuario como, por ejemplo, que
elija tamaños de fuentes distintos, cantidad de columnas a elección, colores e imágenes de
fondo personalizados, etc. Todo esto, simplemente eligiendo cuál hoja de estilos se aplicará,
que se decidirá por el valor almacenado en una cookie).
La secuencia de pasos será ésta:
1. Verifcaremos si el usuario acaba de elegir algún estilo mediante un menú de se-
lección (verifcamos si en $_POST existe la variable que da nombre al select que
hayamos proporcionado para elegir estilos);
2. si lo hizo, almacenaremos en una cookie el nombre del estilo elegido, y además lo
escribiremos dentro de <link>;
3. de lo contrario, si en $_POST no proporcionó nada, verifcamos con otro condicio-
nal si ya tiene la cookie almacenada de antes, leyéndola de $_COOKIE y, en ese
caso, leeremos la variable que fue proporcionada por esa cookie y escribiremos
su valor dentro de la etiqueta <link>;
4. y, por último, si tampoco en $_COOKIE encontramos datos, es que el usuario
llega a la página por primera vez y todavía no eligió nada, así que, en ese caso,
escribiremos un valor por defecto dentro de <link>.
<?php
if ( isset($_POST["eleccion"]) ){
// si el dato está ubicado allí, es que acaban de usar el
formulario y enviaron un estilo elegido.
$hoja = $_POST["eleccion"];
// entonces, dejamos preparada una variable para usarla
dentro de <link>
setcookie("elegido",$hoja,time()+(60 * 60 * 24 * 3 0 ) ) ;
} else {
// si no encontramos en $_POST el dato, vemos si ya estaba
en una cookie desde una visita anterior:
if ( isset($_COOKIE["elegido"]) ){
// si está, colocamos dentro de la misma variable $hoja lo
que el usuario había elegido:
$hoja = $_COOKIE["elegido"];
} else {
// si tampoco estaba allí, mostraremos una hoja por
defecto:
$hoja = "hoja-por-defecto";
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Usando cookies para elegir hoja de estilos</title>
<meta http-equiv="Content-Type" content="text/
html;charset=utf-8" />
<?php
// sea cual sea el camino tomado anteriormente, la variable
$hoja debe tener algún valor, así que lo leemos y lo usamos
para que se cargue la hoja respectiva:
if ( isset($hoja) ) {
}
?>
</head>
<body>
<h1>¡Elijamos un diseño!</h1>
<form action="pagina.php" method="post">
<feldset>
<p>Cambiemos el estilo a nuestro gusto:</p>
<select name="eleccion">
<option value="minimalista">Minimalista</option>
<option value="antigua">Antigua</option>
<option value="moderna">Moderna</option>
<option value="zoom">Fuentes grandes</option>
<option value="tres">Tres columnas</option>
<option value="dos">Dos columnas</option>
</select>
<input type="submit" value="Elegir" />
</feldset>
</form>
</body>
</html>
Para que el rompecabezas funcione, los nombres que le daremos a nuestras hojas de
estilo serán los que hemos usado dentro de este código: “hoja-por-defecto.css”, “minimalista.
css”, “antigua.css”, “moderna.css”, “zoom.css”, “tres.css” y “dos.css”.
Por supuesto, hagamos que los cambios en cuanto a diseño en las distintas hojas CSS
sean notorios, para que al navegar por las distintas páginas de nuestro sitio veamos cómo se
mantiene el estilo elegido al comenzar la navegación.
Agreguemos en cada página de nuestro sitio los contenidos propios de cada página,
e incluyamos un menú para navegar entre ellas, y asegurémonos de repetir tanto el menú de
selección para elegir un estilo, como el código PHP necesario para que lo detecte y lo guarde
en las cookies o lo lea en ellas, completando la etiqueta <link>.
ese archivo es muy importante y consiste en una parte fja (“sess” en este ejem-
plo), más un guión bajo y un código aleatorio único, siempre distinto, que puede
ser similar a esto:
sess_xyza123xyzab12x
2. Y, del lado del usuario, se crea un código que se guarda en una variable de
cookie, o que también puede transmitirse mediante una constante llamada SID
(session identifer, identifcador de sesión) agregada a todos los enlaces o formu-
larios de nuestro sitio. Ese código contiene aquella parte del nombre del archivo
recientemente creado en el servidor que sigue al guión bajo _, por lo cual, en el
ejemplo anterior, el valor del código que estará del lado del usuario será:
xyza123xyzab12x
Figura 7-6. Ambas partes de una sesión: archivo en servidor, y cookie del lado del usuario.
En las siguientes peticiones del usuario, mientras navega por páginas del mismo sitio,
será la llegada de ese código al servidor (ya sea desde una cookie o desde un enlace que
envía el SID) lo que permita relacionar a quien envió ese código con los datos (variables)
guardados en su archivo de sesión respectivo.
A continuación, vamos a tratar de comprender en detalle cómo “se le sigue el rastro” a
un usuario de un sitio Web mediante sesiones.
Habitualmente, sin que utilicemos sesiones, cuando un usuario está en una página y
pulsa un enlace solicitando ver otra página del mismo sitio, el servidor Web no sabe quién
le está haciendo ese pedido de entre los muchos usuarios que pudieron haber solicitado lo
mismo. No sabe que ese usuario estaba viendo anteriormente tal otra página, ni cuánto tiem-
po pasó viéndola. Cada pedido para ver una nueva página, es totalmente independiente de
cualquier solicitud anterior. Entonces, se hace difícil trazar el recorrido que cada usuario realizó
(con fnes estadísticos, para analizar el comportamiento de nuestros usuarios a medida que
navegan por nuestro sitio, o simplemente para mantener datos relacionados con ese usuario,
generalmente usuario y contraseña, a lo largo de toda su visita).
Este problema de olvidar en el servidor lo que el usuario escribió (o seleccionó) en la
página anterior, es clásico de los formularios en varios pasos, ya que van solicitando en dis-
tintas páginas datos y más datos. Antiguamente (más de diez años atrás), esto se soluciona-
ba mediante campos ocultos de formulario (input type=“hidden”), que reenviaban hacia el
servidor todos los datos del usuario que nos interesaba preservar hasta la página siguiente.
Si los datos son demasiados, esto es bastante tedioso (por ejemplo, todos los productos de
un sitio de comercio electrónico que fueron elegidos por un mismo usuario, y la cantidad de
cada uno, o todos los datos personales, laborales y académicos, en el caso de un formulario
en varias páginas de una Web de empleos).
Para resolver este tipo de problema, podemos recurrir a las sesiones, cuyo funciona-
miento consiste en relacionar a un navegador, en un momento en particular, con un código
único. Con solo transmitir ese código de una página a otra, podremos acceder a todo el resto
de datos asociados a ese código que estuvieran guardados en el servidor. A ese código se lo
denomina identifcador de sesión, o Session ID, de allí que su sigla sea SID.
Las sesiones no se “activan” por sí solas, sino ejecutando una función de PHP; pero esa
ejecución puede programarse para que suceda por el solo hecho de llegar a una página, o
mediante alguna acción específca del usuario:
• Por ejemplo, en un catálogo de ecommerce, por el solo hecho de entrar a la
página de inicio, se suele crear automáticamente una sesión, para que se vayan
memorizando en variables de sesión los productos elegidos por el usuario y la
cantidad de cada uno, mientras navega y pasa de una página a otra del catálogo
y va eligiendo más productos, modifcando su cantidad o eliminando alguno de
ellos del carrito de compras. El famoso carrito de compras no es más que variables
almacenadas en un archivo de sesión.
• En otros casos, no se inicia la sesión hasta que el usuario haga algo; por ejemplo,
hasta que escribe su nombre de usuario y contraseña y envía un formulario; en
ese momento, ha iniciado una sesión y ya son identifcables sus datos hasta que
la cierre, puesto que su usuario y contraseña quedaron guardados en variables de
sesión. Este es el caso en un sitio de home-banking, o en un campus virtual, un
webmail, o cualquier otro sitio que requiera identifcarse para acceder.
Básicamente, la tarea que hace una sesión es generar un identifcador único para
cada sesión (una constante llamada SID -Session ID-) y permitir que se le asocien variables,
cuyos valores pertenecerán sólo a esa sesión (ejemplo: los productos elegidos en un carrito
de compra por “ese” usuario).
Se crea un Identifcador SI NO
variable 1 variable 1
variable 2 variable 2
Se declaran variables... variable 3 variable 3
variable 4... variable 4...
(variables de sesión) (variables comunes)
Pasando solamente el ID de
Pasando una por una cada
¿Cómo las transmitimos a la sesión, ya están TODAS las
variable en campos ocultos del
siguiente página? variables de sesión disponibles en
formulario.
la nueva página.
todavía permanece activa, vigente (eso puede ser cómodo en unos casos, y pe-
ligroso en otros). Otra ventaja es que es más difícil el “robo” de sesiones, que un
usuario pase a otro el identifcador de sesión. La gran desventaja de usar cookies,
es que pueden estar desactivadas.
• Por el contrario, en caso de enviar el SID en los enlaces y no utilizar cookies, la
principal desventaja es que, en cuanto salgamos con el navegador hacia otro sitio
distinto del nuestro, la sesión habrá caducado (luego, cuando regresemos al sitio,
tendremos que crear una sesión nueva, diferente a la anterior). Otra desventaja es
que deberemos modifcar a mano cada enlace del sitio y cada formulario, algo
relativamente fácil en un sitio nuevo, pero posiblemente muy difícil en un sitio ya
existente. Y otra desventaja más es que, en un instante, el identifcador de sesión
se puede enviar de un usuario a otro, y podría haber dos personas utilizando una
misma sesión (algo propicio para fraudes y otros engaños). La única ventaja es
que no se depende de las cookies y, por lo tanto, siempre estará disponible este
método para todos los usuarios.
Ambas posibilidades tienen sus ventajas y sus contras, tendremos que pensar en cada
caso qué nos convendría utilizar, según nuestros objetivos y usuarios.
Cualquiera sea la forma que elijamos, lo verdaderamente imprescindible es mantener
disponible el identifcador de sesión a lo largo de la navegación entre varias páginas de un
mismo sitio, ya que sin obtener página tras página el identifcador de sesión activa, el servidor
no podría acceder a las variables de sesión de ese usuario.
session.save_path = "/tmp"
o, si se trata de un servidor local que use Windows, ruta que incluya el disco, y usando barras
invertidas:
session.save_path = "C:\temp"
relativas a sesiones (busquemos el texto session en esa página). Allí veremos los valores
dados a la confguración de sesiones en el php.ini de ese hosting (sólo que cambiar alguno
de ellos quedará supeditado a la voluntad y calidad del servicio de cada empresa de hosting
en particular).
Como ya sabemos, para ejecutar phpinfo() simplemente escribiremos esto:
<?php
phpinfo();
?>
<?php
ini_set("session.save_path", "/ruta/deseada");
?>
La “ruta” será aquella carpeta donde queramos que se guarden nuestros archivos de
sesión. Por supuesto, antes crearemos la carpeta con nuestro programa de FTP y le daremos
los permisos de escritura. Si encontramos problemas, es recomendable consultar al soporte
de nuestra empresa de hosting para que nos orienten.
<?php
session_start();
$identifcador = session_id();
echo "El identifcador de esta sesión e s : $identifcador";
?>
La función session_start debe incluirse en todas las páginas en las que se pretenda
seguir con una sesión activa, si ya la hubiera, o empezar una nueva.
Un detalle importantísimo es que debe ser lo primero que se colocará en la página,
antes de cualquier salida de código por print o echo, ya que la sesión intenta defnir una
cookie en el usuario, y esta capacidad sólo puede ejecutarse cuando los encabezados de la
petición HTTP (los headers) aún no han sido enviados.
Si hubiera tan sólo un espacio en blanco, o un carácter, o una etiqueta HTML, o, incluso,
la DTD del archivo antes de usar la función que las crea, ésta no funcionará y provo-
cará un error.
<?php
session_start();
$_SESSION["nombre"] = "pepe";
/* desde ya que ese dato en vez de asignarlo aquí, podría venir
de un formulario, o de un enlace.
Por ejemplo:
$_SESSION["nombre"] = $_POST["campoX"];
o bien:
$_SESSION["nombre"] = $_GET["enlaceX"];
*/
echo "Hola: ".$_SESSION["nombre"];
?>
<html>
<!-- etc -->
<p><a href="pagina2.php">Siguiente página</a></p>
<!-- etc -->
</html>
nombre|s:4:"pepe";
Del lado opuesto, en el disco del usuario, se ha creado una cookie que contiene una
constante llamada PHPSESSID con un valor único, correspondiente al nombre del archivo
de texto creado en el servidor. Ese código es el único dato que almacenará la cookie del lado
del usuario, y servirá para identifcarlo. Ver Figura 7-8.
session.use_only_cookies = On
Al estar confgurado en On, nos obliga a usar cookies, y no funcionará ninguna otra
alternativa. En cambio, si está confgurado en Off, podremos usar métodos alternativos, sin
cookies.
Si tenemos acceso al archivo php.ini, en un servidor local, veremos que, en ese caso,
contendrá una línea que dice:
session.use_only_cookies = 1
<?php
session_start()
echo "Su nombre e s : ".$_SESSION["nombre"];
?>
<html>
<!-- etc -->
<p><a href="pagina1.php?<?php echo SID;?>">Volver</a></p>
<!-- etc -->
</html>
Cuando veamos este enlace en nuestro navegador, veremos que, en realidad, esa or-
den que muestra la constante SID “escribió” dentro del enlace algo similar a esto:
pagina1.php?PHPSESSID=jvav952q2ek0l8g9tjp5g7rur3
<?php
session_start();
$_SESSION["dato"] = "clientenuevo";
?>
<form action="pagina2.php?<?php echo SID; ?>">
<input...etc...>
</form>
<?php
session_start();
$_SESSION["dato"] = "clientenuevo";
?>
<form action="pagina2.php?<?php echo session_name();?>=<?php
echo session_id();?>">
<input...etc...>
</form>
$_SESSION["dato"] = "";
<?php
session_start();
unset($_SESSION["dato"]);
// si a continuación queremos usar esa variable, no estará más
disponible:
echo $_SESSION["dato"]; // producirá un error
?>
Incluso, podemos eliminar todas las variables de sesión (y sus valores, por supuesto)
de una sola vez con:
$_SESSION = array();
Pero, tanto si eliminamos una sola o pocas variables de sesión, como si eliminamos
todas las variables de sesión de una vez, debemos tener presente que no estamos eliminan-
do el archivo de sesión del servidor, ni la cookie almacenada en el navegador, por lo cual
la sesión que relaciona a este usuario con su archivo en el servidor sigue activa, aunque sin
datos almacenados.
<?php
session_destroy();
?>
provocaría un mensaje de error; es preciso que en la página “de salida”, en la que cerramos
la sesión, la retomemos antes de cerrarla:
<?php
session_start();
session_destroy();
?>
Hasta aquí, hemos eliminado del servidor el archivo de sesión y todas sus variables.
Pero todavía en el navegador existe la cookie.
Una forma más rotunda de eliminar la sesión (y es la que recomendamos utilizar) sería
la siguiente:
<?php
// 1 . Retomamos la sesión
session_start();
session_destroy();
?>
Notemos que en el condicional averiguamos si se está utilizando una cookie para trans-
mitir el identifcador de sesión, y si esto es cierto, entonces procedemos a leer todos los
parámetros de esa cookie ejecutando la función session_get_cookie_params(), para, a con-
tinuación, usar esos parámetros dentro de una nueva ejecución de la función setcookie, que
eliminará la cookie al haber defnido su tiempo de expiración en el pasado.
<?php
session_start();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Zona de acceso restringido</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
</head>
<body>
<?php
// 1 . Si acaban de enviar el formulario de acceso, leemos
de $_POST los datos:
if( isset($_POST["usuario"]) and isset($_POST["clave"]) ){
</ul>
</div>
<div id="formulario">
<form name="acceso" method="post" action="index.php">
<feldset>
<legend>Ingrese sus datos de acceso:</legend>
<label for="usuario">Su usuario:</label><input type="text"
id="usuario" name="usuario" /><br />
<label for="clave">Su clave:</label><input type="text"
id="clave" name="clave" /><br />
<input type="submit" id="ingresar" name="ingresar"
value="Ingresar" /><br />
</feldset>
</form>
</div>
</body>
</html>
<?php
session_start();
if( isset($_SESSION["usuario"]) and $_SESSION["usuario"]<>""){
<div id="menu">
<ul>
<li><a href="primera.php">Primera página privada</a></li>
<li><a href="segunda.php">Segunda página privada</a></li>
<li><a href="tercera.php">Tercera página privada</a></li>
</ul>
</div>
<?php
// Recién aquí cerramos el if
} else {
?>
<p>La sesión no está abierta, por favor utilice el <a
href="index.php">formulario de acceso</a></p>
<?php
}
?>
<?php
session_start();
if ( isset($_POST["idioma"]) ) {
$_SESSION["idioma"] = $_POST["idioma"];
$idioma = $_SESSION["idioma"];
include("idiomas/$idioma.php");
} elseif ( isset($_SESSION["idioma"]) ) {
$idioma = $_SESSION["idioma"];
include("idiomas/$idioma.php");
} else {
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- etc. -->
</head>
<body>
<div id="titulo"><?php echo TITULO; ?></div>
<div id="subtitulo"><?php echo SUBTITULO; ?></div>
<div id="avance"><?php echo AVANCE; ?></div>
<div id="noticia"><?php echo NOTICIA; ?></div>
etc...
<div id="menu">
<form name="formu1" method="post" action="index.php">
<feldset>
<legend>Elija su idioma</legend>
<select name="idioma">
<option value="espanol">Castellano</option>
<option value="ingles">English</option>
</select>
<input type="submit" value="Elegir" />
</feldset>
</form>
</div>
</body>
</html>
idiomas/espanol.php
idiomas/ingles.php
idiomas/frances.php
etc.
Estos archivos contienen TODOS los textos del sitio, almacenados en LOS MISMOS
nombres de constantes:
Contenido del archivo espanol.php:
<?php
defne("TITULO", "Bienvenidos a mi sitio en castellano");
defne("SUBTITULO", "Este es un subtítulo en castella
no...");
defne("AVANCE", "Este es un texto complementario...");
defne("NOTICIA", "Este es el texto largo en
castellano...");
?>
<?php
Para agregar otros idiomas, simplemente necesitaremos añadir una opción más al
menú select HTML por cada idioma, para que le deje elegir ese idioma al usuario. Ese select
debe tener un atributo name cuyo valor sea “idioma”, para que genere $_POST[“idioma”],
que es lo que damos por supuesto en este código; luego de validar su presencia con isset,
guardaremos el idioma elegido en una variable de sesión. Por supuesto, también debemos
crear el archivo con los textos en ese idioma dentro de la carpeta “idiomas”.
Podemos crear todas las páginas del sitio que queramos, con enlaces entre ellas, que
memorizarán el idioma elegido por el usuario a lo largo de todas ellas (si la cantidad de
páginas o el largo de los textos lo justifcan, será conveniente crear varios archivos con las
defniciones de los textos, quizás uno por sección del sitio, o, incluso, uno por cada página
del sitio, para no obligar a leer completo un sólo archivo extremadamente largo en todas las
páginas del sitio; solo será cuestión de “avisar” con alguna variable en cuál sección o página
nos encontramos, para leer el archivo respectivo, de forma similar a como lo estamos hacien-
do ahora para elegir el archivo de idioma).
Y con esto damos por fnalizada nuestra introducción al manejo de sesiones y de
cookies en PHP. Ya estamos en condiciones de identifcar a nuestros usuarios, y podemos
crearles contenidos personalizados y “perdurables” a lo largo de una sesión.
Esto, que en un primer momento no parecería ser demasiado útil, se vuelve una herra-
mienta imprescindible para poder trabajar con grandes cantidades de información. Pense-
mos –por ejemplo– en una página que deba mostrar un elemento select HTML que contenga
una lista de años: desde el 1800 hasta el 2020. En vez de hacer 220 órdenes echo, una para
cada option del select, podemos hacer una sola orden echo pero dentro de un bucle, que
comience en el 1800 y muestre de a un option por vuelta, mientras no se haya llegado al
2020. Un par de líneas de código, en vez de centenares.
Imaginemos que tenemos que mostrar miles de nombres de empleados de una em-
presa, nombres almacenados dentro de un archivo de texto, a razón de uno por línea. Nada
mejor que un bucle para que lea “de a una” línea de texto por vez.
Son muchísimos los usos de los bucles, ya lo veremos a medida que avancemos en
este capítulo. Pero son ideales para tres tareas fundamentales:
1. leer datos de matrices,
2. leer flas de archivos de texto,
3. leer registros traídos de una base de datos.
Existen cuatro tipos distintos de bucles en PHP: for, while, do while y foreach. A
continuación, veremos cuáles son los usos ideales de cada uno de ellos, mediante ejemplos
listos para usar.
Hoy es el día 1
Hoy es el día 2
Hoy es el día 3
etc...
Hoy es el día 31
En vez de escribir 31 líneas de código con 31 echos o prints (uno por cada frase, por
cada día del mes), podemos lograr idéntico resultado mediante un bucle for, en sólo un par
de líneas de código:
Este tipo de ciclo o bucle for se utiliza para ejecutar una orden a repetición un número
exacto de veces; es decir, el número de repeticiones debe conocer con anterioridad (en este
caso, sabemos la cantidad de días del mes en cuestión: 31).
Como podemos observar, en el ejemplo anterior, este tipo de bucle denominado for
tiene los siguientes elementos:
1. Inicialización de una variable: allí se le dá un valor inicial a una variable que será
el elemento “clave” dentro del bucle. Esta inicialización se ejecuta antes de que
comience el bucle, por única vez.
En el ejemplo anterior, corresponde a esta parte:
$dia=1;
En este ejemplo, le damos el valor inicial 1 (pero puede ser cualquier otro).
2. Evaluación del valor de esa variable: se evalúa si el valor de la variable que fue
inicializada todavía está dentro del rango defnido, es decir, si la condición con-
$dia<32;
Si $dia vale menos de 32, será verdadera, y se ejecutará una vez el código envuel-
to entre las llaves del bucle, es decir, este código:
$dia=$dia+1;
Cualquiera sea el tipo de modifcación que hagamos con el valor de la variable clave, el
objetivo es que tome todos los valores por los que decidamos que pase (en este último
ejemplo, decidimos que recorra todos los números pares, de dos en dos, desde el cero
hasta el 100 inclusive), hasta que, en un determinado momento, el valor “se salga” del
rango (con el valor 100, en este ejemplo, que ya no es menor a 100) y, por lo tanto, la
condición sea evaluada como falsa, y se termine el bucle. ¡No queremos bucles infni-
tos!... debemos asegurarnos de que siempre, en algún momento, la modifcación que
defnimos termine cambiando el valor de la variable a otro en el cual la condición ya no
se cumpla.
Si escribimos, paso a paso, los valores que toman las variables, comprenderemos me-
jor el funcionamiento repetitivo de los bucles. Pondremos a prueba el bucle del ejemplo,
mostrando los valores de las variables paso a paso.
En un primer momento, se ejecuta la inicialización de la variable clave, en la que noso-
tros mismos defnimos que $dia vale 1 .
De esta manera, en el inicio, la condición fjada ($dia < 32) se evalúa como verdadera,
ya que 1 realmente es menor a 32.
Por lo tanto, se ejecuta el código envuelto entre las llaves del bucle (el echo) una vez,
y se escribe esto en el lugar exacto en el que estaba escrito ese código dentro de nuestra
página:
A continuación de esa ejecución del código envuelto entre las llaves del bucle, se ejecu-
ta la modifcación (el incremento, en este caso) de la variable $dia, que pasa a valer 2. Con
esto, se termina la primera vuelta del bucle.
Luego, para comenzar la segunda vuelta del bucle, ya no se inicializa la variable $dia
(recordemos que dijimos que se le da un valor inicial solamente una vez).
Directamente, se evalúa la condición sobre la base del nuevo valor que tomó la variable
$dia (por ahora, un 2). Como 2 todavía es menor a 32, la condición es verdadera también en
esta vuelta, y se ejecuta una vez más el código envuelto entre las llaves del bucle, el echo,
que produce esta vez un resultado levemente distinto al anterior, ya que $dia ahora vale 2, en
consecuencia escribirá:
y $dia se modifca, y pasa a valer 4. Y así sucesivamente... hasta que $dia llegue a valer 31.
Entonces, se escribe esto:
Veamos, entonces, un ejemplo de cómo resulta simple y útil utilizar un bucle for para
mostrar una sencilla matriz cargada con productos:
<?php
$productos = array(1 => "manzanas","naranjas","peras",
"uvas");
El concepto de contador
Hemos visto que los tres elementos de un bucle for eran la inicialización de una variable,
su evaluación y su modifcación. Este último elemento aplica una estructura típica en pro-
gramación, denominada contador. Un contador lleva la cuenta de algo en una variable. Es
decir: guarda, en una misma variable, el resultado de sumar “lo que ya valía esa variable”, más
un número.
Por ejemplo, pensemos en alguien que cuenta las vueltas de un auto alrededor de un
circuito de carreras. Cuando arranca, el contador está en cero:
$vueltas = 0 ;
Cuando el auto complete la primera vuelta y pase por la línea de largada, le debe sumar
“uno” a la cantidad anterior de vueltas, por lo que quedaría así:
$vueltas = $vueltas + 1 ;
Esto se leerá así: “guardar en $vueltas lo que ya valía $vueltas, más 1”.
De esta manera, al terminar la primera vuelta, $vueltas vale 1 , ya que $vueltas valía
inicialmente 0 y, como le sumamos 1 , 0 + 1 = 1 .
Al terminar de dar otra vuelta, se vuelve a ejecutar esa misma operación:
$vueltas = $vueltas + 1 ;
Como $vueltas valía 1 , al sumarle 1 , pasa a valer 2. Ahora $vueltas vale 2, y así
sucesivamente.
La estructura es siempre la misma: que la variable sea igual a lo que valía, más un
número.
Si el número que estamos sumando es un 1 (que es lo más común), podemos abreviar
la notación del contador de esta manera:
$vueltas++;
Eso es, exactamente, lo mismo que escribir: $vueltas = $vueltas + 1 . Por eso, una no-
tación típica en los bucles for es la siguiente:
El tercer elemento del bucle que dice $i++ es un contador que en cada vuelta del bucle
le suma 1 a lo que ya valía $i .
Pero el número que le sumamos no debe ser necesariamente un 1. También podemos
contar de dos en dos, de tres en tres, de cien en cien, o con el intervalo que queramos, pero
ese intervalo es fjo; es decir, siempre es el mismo mientras usemos ese contador. Si empe-
zamos a contar de dos en dos, ese contador contará siempre de dos en dos, no será posible
que en una vuelta sume 1 y en otra 3, por ejemplo (esto lo veremos cuando aprendamos la
estructura “acumulador”). Pero, aquí, en el “contador”, el valor que se incrementa en cada
vuelta puede ser cualquier número, pero a lo largo del funcionamiento del contador ese
número no cambiará.
Veamos un ejemplo de “dos en dos”:
$medias = 0 ;
$medias = $medias + 2 ;
$medias = $medias + 2 ;
La variable $medias pasa a valer 4, y así sucesivamente. A simple vista, es muy fácil
reconocer esta tipo de estructura, ya que veremos el nombre de una variable, un signo
igual, otra vez el nombre de la misma variable, y luego la operación que la modifca en un
número fjo:
$vuelta = $vuelta + 1 ;
Asimismo, utilizamos la estructura de contador para que el valor de una variable dis-
minuya en intervalos fjos:
$falta = $falta - 1 ;
En el caso de que el decremento sea de a 1 por vuelta, también existe una notación
abreviada, con un doble signo menos:
$falta--;
El concepto de acumulador
Muy similar a la estructura anterior, el acumulador es una variable que va almacenando valores
dentro de ella, pero cada incremento no necesariamente es igual al anterior, como en el caso
del contador, donde siempre sumábamos la misma cantidad debido a que era una constante
(un número fjo). En un acumulador, el incremento se lee de una variable, por lo cual puede
ser siempre distinto. Es muy útil para almacenar totales y subtotales, calcular el importe de
una compra sumando los importes parciales, etc.
A simple vista, se reconoce esta estructura porque consiste en una variable que es igual
a sí misma más otra variable:
Por ejemplo, pensemos en alguien que está acumulando la suma de una compra.
Cuando arranca, el acumulador está en cero:
$importe = 0 ;
Cuando ingresemos el precio del primer producto, debemos sumar ese precio al acu-
mulador, por lo que quedaría así:
Esto se leería: “guardar en $importe lo que ya valía $importe más lo que vale la variable
$precio”.
De esta manera, al terminar de cargar el primer producto (supongamos que costaba
$50), los números serán: 0 + 50 = 50. La variable $importe ahora vale 50.
Al terminar de cargar otro producto (supongamos que esta vez costaba $345), se vuel-
ve a ejecutar la misma operación:
Como $importe valía 50, los números serán: 50 + 345 = 395. La variable $importe ahora
vale 395. Y así sucesivamente...
La estructura del acumulador, entonces, consiste en una variable que es igual a su valor
anterior, más un nuevo número variable, que no es fjo. De la misma manera que con los con-
tadores, también existe una abreviatura para los acumuladores:
$importe += $precio;
$importe -= $precio;
Muy pronto, en este capítulo, aplicaremos estas estructuras –tanto el contador como el
acumulador– dentro de bucles.
En cada vuelta del bucle, leerá una celda de la matriz y colocará su valor dentro de
la variable $valor. En la siguiente vuelta, leerá el elemento siguiente de la matriz, y así hasta
terminar el contenido de la matriz completa.
Veamos el siguiente ejemplo:
Archivo foreach.php:
<?php
$animales[4] = "Perro";
$animales[5] = "Gato";
$animales[21] = "Tortuga";
$animales[3] = "Hamster";
$animales[45] = "Canario";
La segunda sintaxis posible de foreach nos permite que, en cada vuelta del bucle, no
sólo leamos el valor de la celda de la matriz, sino también el índice de esa celda, y lo alma-
cenemos en otra variable:
<?php
$animales[4] = "Perro";
$animales[5] = "Gato";
$animales[21] = "Tortuga”;
$animales[3] = "Hamster";
$animales[45] = "Canario";
Este tipo de bucle foreach (comúnmente utilizado con su sintaxis simple, la que solo lee
un valor), debe ser la primera opción cuando recorremos una matriz, debido a su efciencia
y sencillez.
En cada vuelta, este bucle lee el resultado de una apuesta imaginaria, proporcionada
por una supuesta función denominada leerApuesta (por supuesto, hasta que no sepamos
defnir esta función será imposible probarlo). Por lo tanto, no sabemos cuántas vueltas dará
antes de encontrar que el valor de $ganador es SI. Para este tipo de bucles –que dependen
de una condición en la que no podemos prever cuándo será verdadera–, es ideal el uso de
un bucle de tipo while.
Veamos un ejemplo más para que notemos lo complejo que puede resultar la utilización
del tipo de bucle “incorrecto”. En el cuadro que sigue, se muestra cuán complejo resulta un
while para recorrer una matriz (tarea que realiza con mucha mayor simpleza el bucle foreach):
<?php
while (list($clave,$valor) = each($_POST["numeros"])){
Este código recorrerá la matriz $_POST[“numeros”] sin importar cuál sea su longitud,
o de qué tipo sean sus índices (alfanuméricos o numéricos e, incluso, desordenados). A
continuación, veremos cómo operan estas dos funciones accesorias que hemos necesitado
agregar: por un lado, la función list, y, por el otro, la función each.
<?php
$datos["nombre"] = "Juan Pérez";
$datos["edad"] = 2 4 ;
$datos["estado"] = "casado";
$datos["sueldo"] = 800;
$este = each($datos);
/* Convierte a $este en una matriz de 4 celdas
Para visualizarlo, imprimiremos las 4 celdas de $este:*/
print("El índice de este elemento es ".$este[0]."<br / > " ) ;
print("El valor de este elemento es ".$este[1]."<br / > " ) ;
print("El índice de este elemento es ".$este["key"]."<br
/>");
print("El valor de este elemento es ".$este["value"]."<br
/>");
?>
Notemos que each convirtió a $este en una matriz de cuatro elementos: los dos pri-
meros tienen índices numéricos: el índice del primer elemento creado es un 0, el del segundo
un 1 , y contienen, respectivamente, el que era el índice del elemento de la matriz $datos
que se leyó en esta vuelta del bucle (“nombre”, en este ejemplo), y el valor de ese mismo
elemento (“Juan Pérez”, en este caso).
Luego, el tercero y cuarto elementos de esa matriz denominada $este, que fue crea-
da por each, vuelven a contener la misma información repetida (“nombre” y “Juan Pérez”),
pero, esta vez, con índices alfanuméricos llamados key y value (clave y valor).
En el ejercicio anterior, para ganar en claridad, hemos simplifcado y utilizamos sólo las
primeras dos celdas creadas por each: en la primera almacenamos el índice y, en la segunda,
el valor de ese elemento seleccionado. Pero, en vez de adjudicarle esos dos datos a una
variable/matriz (como $este), se los adjudicamos mediante la función list a dos nuevas va-
riables que recibirán esos datos: list($clave,$valor).
La función list guarda en la variable $clave la clave del elemento de la matriz leído
por each y, en $valor, guarda el valor de ese elemento. Otra vez, “nombre” y “Juan Pérez”,
respectivamente.
Entonces, hacemos el bucle while “mientras” el list($clave,$valor) sea igual al each de
$numeros. Es decir, mientras se pueda producir esta asignación de datos de each hacia list.
Mientras each pueda leer datos de una celda de la matriz original, y pueda pasársela a las dos
variables que list tiene preparadas, a la espera.
Copiamos el código nuevamente aquí para volver a examinarlo prestando atención a
los detalles:
Archivo list-each.php:
<?php
while (list($clave,$valor) = each($_POST["numeros"])){
print("El elemento ".$clave." contiene un
".$valor."<br / > " ) ;
}
?>
En cada vuelta del bucle, las variables $clave y $valor contendrán el índice y el valor
del elemento que each acaba de leer.
Se saldrá del bucle cuando sea falsa esa asignación (cuando el valor que lea each de
la matriz original ya no se pueda transferir a list... porque each no haya podido leer nada); es
decir: cuando se haya recorrido hasta el último elemento inclusive de la matriz $numeros, y ya
no quede ningún elemento más que se pueda leer con each.
Este método es una alternativa al foreach para recorrer matrices de índices alfanumé-
ricos, o numéricos no consecutivos. Desde ya que foreach es mucho más simple, pero no
todos los programadores lo utilizan, y nos encontraremos muchas veces con códigos que
utilizan while combinado con list y con each. Ya estamos en condiciones de comprender
esos códigos.
El bucle do-while
Una variante del bucle while, que se utiliza menos, es la del bucle do-while. Es similar a la
primera, pero su condición se evalúa al fnal de cada vuelta, no al principio. De este modo, se
“garantiza” que se ejecutará al menos una vez el bloque de código envuelto entre las llaves
del do-while, ya que la condición se evaluará luego de la primera ejecución de ese bloque de
código y no cuando se inicia el bucle. En un bucle while normal ocurría lo contrario, puesto
que la condición se ejecutaba antes de la primera vuelta, por lo tanto, podía suceder que fuera
falsa, y que nunca se ejecutara el código dentro del while.
La sintaxis de este tipo de bucle es la siguiente:
<?php
$limite = 5 ;
do {
echo $limite;
} while ($limite>9);
?>
El echo encerrado entre las llaves del bucle se ejecutará, al principio, una sola vez y,
luego, cuando se evalúe la condición, se comprobará su falsedad ($limite vale 5 y, por lo
tanto, no es mayor a nueve), en consecuencia, se dará por terminada la ejecución. Pero ya se
ejecutó una vez el código encerrado entre sus llaves.
Prestemos atención al detalle de que la línea que defne la condición, en el do-while
debe fnalizarse con un punto y coma (a diferencia del while, que no lo lleva).
<?php
$productos = array(1 => "manzanas","naranjas","peras",
"uvas");
$cuantos = count($productos);
echo "<table>";
if ($i%2 == 0){
echo '<tr class="par"><td>La fla de
'.$productos[$i].' es par</td></tr>';
} else {
echo '<tr class="impar"><td>La fla de
'.$productos[$i].' es impar</td></tr>';
}
}
echo "</table>";
?>
Si simplemente defnimos en la hoja de estilos CSS un color distinto para alguno de los
class “par” o “impar”, lograremos que nuestra tabla se vea así:
Esto puede lograrse con sólo con esta breve declaración en la hoja de estilos CSS:
.par {
background-color: #999;
color: #fff;
}
<?php
$claves = array(1 => "secreta","ultra","anonima","123456");
$cuantos = count($claves);
// Declaramos la señal
$encontrada = "no";
?>
Figura 8-3. Uso de archivos de texto como lugar donde almacenar datos y de donde leerlos
automáticamente.
De las formas de almacenamiento permanente (no cuentan las variables ni las ma-
trices porque son “volátiles”), el guardar los datos en un archivo de texto es la más simple
de utilizar (y, por supuesto, también las bases de datos, que trataremos en otro capítulo; sin
embargo, quizás nos sorprendería saber que muchas bases de datos, en el fondo, guardan
sus datos en archivos de texto ubicados en el servidor).
Aprenderemos de qué maneras se puede guardar automáticamente información den-
tro de archivos de texto, y de qué formas se puede leer esa información ya almacenada en
dichos archivos.
La interacción automática entre nuestras páginas PHP y los archivos de texto (salvo una
sola excepción que ya veremos), sigue siempre estos tres pasos consecutivos, en este orden:
1 . Abrir el archivo.
2. Hacer alguna operación con el contenido de ese archivo.
3. Cerrar el archivo.
A continuación, veremos estos pasos en detalle:
Existen algunos otros modos adicionales, pero como no son tan usados, los dejamos
para una eventual profundización sobre el tema que quiera realizar el lector.
Para comprender cómo funciona el primer paso de la apertura de un archivo en un
“modo” determinado, veremos un ejemplo de uso de fopen:
<?php
$abierto = fopen ("archivo.txt", " r " ) ;
?>
Esta línea abre un archivo para leer su contenido (ya que especifcamos el modo “r”
–read–), y crea una variable ($abierto) que será el identifcador de ese recurso disponible (el
archivo ya abierto); con ese identifcador nos referiremos, de aquí en más, al archivo ya abierto
durante la ejecución de las siguientes operaciones de lectura, agregado o escritura.
Además, como esa variable contiene el resultado de la operación de apertura, según el
intento haya sido “verdadero” o “falso”, podemos preguntar con un if si se pudo abrir el ar-
chivo, si devolvió un “verdadero” la ejecución de esa función, antes de seguir realizando otras
tareas posteriores que den por sentado que el archivo fue abierto:
Una vez abierto el archivo, seguramente será de nuestro interés hacer algo, es decir, realizar
alguna operación con los datos del archivo abierto (si no, ¿para qué lo abrimos?).
Las posibles operaciones son:
• la lectura de datos del archivo,
• la escritura de nuevos contenidos dentro del archivo, que reemplacen todo otro
contenido anterior,
• y el agregado de nuevos datos al archivo, sin eliminar lo que existía dentro del
archivo.
A estas tres operaciones las describiremos en detalle unos párrafos más adelante, en
este mismo capítulo.
3. Cierre de un archivo
En todos los casos, terminada alguna de esas tres posibles operaciones que acabamos de
mencionar, cerraremos el archivo, para que no ocupe memoria innecesariamente (de la mis-
ma manera que cuando trabajamos en nuestra propia PC, donde cerramos los archivos a me-
dida que los dejamos de usar, para evitar sobrecargar la memoria RAM de nuestra máquina).
El cierre de un archivo se realiza con la función fclose (fle close, o cerrar archivo), que
requiere que entre sus paréntesis especifquemos la variable que hacía de identifcador de
recurso que creamos al momento de abrir el archivo (en nuestro ejemplo: $abierto).
Ejemplo de cierre de un archivo abierto:
<?php
$abierto = fopen ("archivo.txt", " r " ) ;
// Aquí leeríamos, o escribiríamos, o añadiríamos algo...
// y fnalmente, lo cerraríamos:
fclose ($abierto);
?>
Ahora que ya sabemos abrir y cerrar un archivo, estamos preparados para aprender
en detalle en qué consisten las operaciones realmente importantes que se pueden realizar
con los contenidos de un archivo de texto: operaciones de lectura, escritura o agregado
de datos, que realizaremos una vez que el archivo esté abierto, y antes de cerrarlo.
archivo de texto, en una celda dentro de una matriz, para que después la recorramos con
un bucle (tal como aprendimos en el capítulo anterior), y utilicemos esos datos, ya sea para
realizar alguna operación o para mostrarlos directamente al usuario.
El único parámetro que necesita que escribamos entre sus paréntesis es la ruta hacia
el archivo que se leerá (si el archivo está en la misma carpeta que el archivo PHP que se está
ejecutando, será sufciente con que escribamos el nombre del archivo):
<?php
$archivo = "datos.txt";// La ruta al archivo
$lineas = fle($archivo);
// A $lineas lo convertimos en una matriz con tantas celdas
como
}
?>
Es decir, que $lineas[0] tendrá almacenada la primera línea del archivo de texto (recor-
demos que las matrices numeran sus celdas desde cero, por esta razón, lo ajustamos en el mo-
mento de mostrarlo, sumándole 1 en la parte que decía: $i+1, para evitar que dijese “La línea 0...”
y hacer que diga “La línea 1...”), $lineas[1] contendrá la segunda línea, y así sucesivamente. A
continuación, en este ejemplo hemos realizado un bucle for para recorrer la matriz $lineas desde
su primera hasta su última celda (para saber cuántas celdas tiene, ejecutamos la función count).
Dentro del bucle, el intérprete de PHP simplemente ha ido escribiendo, celda por celda, todo
el contenido de la matriz $lineas, por lo tanto, indirectamente, hemos mostrado todo el con-
tenido del archivo de texto original, línea por línea, de principio a f n .
Haciendo uso de esta función, podríamos crear una aplicación que nos permitiera mos-
trar frases aleatorias (o imágenes aleatorias) dentro de nuestras páginas, simplemente “mez-
clando” la matriz una vez leída, y usando sólo una de sus celdas, que siempre contendrá algo
distinto.
Si lo hacemos con frases, debemos asegurarnos de que cada frase ocupe un sólo
renglón dentro del archivo de texto, es decir, se considerará una frase diferente cada vez que
exista un salto de línea, un enter.
Por ejemplo, éste sería el archivo frases.txt:
Piensa como piensan los sabios, mas habla como habla la gente
sencilla – Aristóteles.
Tanto si piensas que puedes, como si piensas que no puedes,
estás en lo cierto – Henry Ford.
Todo lo que somos es el resultado de lo que hemos pensado;
está fundado en nuestros pensamientos y está hecho de nuestros
pensamientos – Buda.
<?php
$archivo = "frases.txt";// La ruta al archivo
$frases = fle($archivo);
// A $lineas lo convertimos en una matriz con tantas celdas
como líneas -renglones- tenía el archivo de texto.
?>
Este código, una vez leída y mezclada la matriz, y obtenida la primera de sus celdas,
utilizará el nombre de foto que leyó para completar una etiqueta img:
<?php
$archivo = "fotos.txt";
$fotos = fle($archivo);
shuffe($fotos);
?>
En muchas otras ocasiones, no nos será útil acceder al archivo para leerlo de a una línea
completa por vez, como hace la función fle, sino que tendremos almacenada muy poca in-
formación: apenas una sola palabra, o una sola línea, o un número. Por ejemplo, un contador
de visitas de una página que tenga guardada la cifra de visitas dentro de un archivo de texto.
Tal vez necesitemos abrir un archivo no para leerlo, sino para escribir datos en él.
Para estos casos, disponemos de varias funciones que, a diferencia de fle, siempre
ejecutan la misma rutina para acceder al archivo:
1) Abren el archivo.
2) Ejecutan alguna operación con los datos del archivo.
3) Cierran el archivo.
Para que nuestras páginas puedan leer datos almacenados en un archivo (además de
la función fle, que ya hemos visto y que no requería ni de apertura ni de cierre del archivo)
aprenderemos a utilizar las siguientes funciones: fpassthru, fread, fgetc, fgets, fgetss.
A continuación, consideraremos en qué caso conviene utilizar cada una de ellas.
Función fpassthru
La función fpassthru (fle pass through o pasar a través del archivo) lee y, a la vez, escribe (no
precisa ni un echo ni un print) la totalidad del contenido de un archivo de texto. Lo muestra
entero, de principio a f n .
<p>
<?php
$abierto = fopen ("noticia.txt", " r " ) ;
fpassthru ($abierto);
fclose ($abierto);
?>
</p>
Para que esto funcione, deberemos crear, con el bloc de notas, un archivo de texto
denominado noticia.txt, y le escribiremos algunas líneas de contenidos (una supuesta noticia):
<p>La noticia del día es que llueve sobre mojado. Pero siem-
pre que llovió, paró...</p>
Función fread
Esta función también permite leer un archivo de texto. A diferencia de fle, que lee por
renglones, y de fpassthru, que lee el archivo entero y lo muestra, la función fread (fle read
o lectura de archivo) lee una cantidad exacta de caracteres de un archivo; además del
identifcador del archivo abierto (que, en los ejemplos anteriores, denominamos $abierto),
necesita que le indiquemos la cantidad exacta de caracteres que leerá (en ejemplo si-
guiente, 15).
La cantidad máxima de caracteres que fread puede leer son 8192 (en realidad, se trata
de bytes más que de caracteres, por lo tanto, se cuentan también los caracteres no imprimi-
bles, como los saltos de línea, tabuladores, etc.). Entonces, es importante que consideremos
que para leer archivos de más de 8Kb de tamaño, ya no podremos usar fread.
Veamos entonces un ejemplo de fread:
<?php
$abierto = fopen ("noticia.txt", " r " ) ;
$principio = fread ($abierto,18);
fclose ($abierto);
print ($principio);
?>
Esto mostrará sólo los primeros 18 caracteres del archivo. Suponiendo que usamos
el mismo archivo de texto anterior, cuando llamemos a fread con ese límite, obtendremos
solamente esta parte del contenido del archivo de texto:
Entonces, la función fread se usa para leer textos pequeños, “frases del día” o frases
célebres, comentarios breves, números, etc.
Función fgetc
Veamos otra función para leer datos de un archivo de texto. La función fgetc (fle get
character o traer un caracter de un archivo) como su nombre lo indica, lee un sólo carac-
ter de un archivo. En los (rarísimos) casos en los que hay que leer únicamente un carácter,
se usa así:
<?php
$abierto = fopen ("noticia.txt", " r " ) ;
Su utilidad radica en que puede usarse dentro de un bucle que recorra todo el con-
tenido del archivo de texto letra por letra, o hasta que aparezca un determinado caracter
especial de fnalización.
Pero, para que esto ocurra, primero necesitamos aprender una función estrechamente
ligada a esta tarea y que se denomina feof.
Función feof
La función feof (fle end of fle o fnal de archivo del archivo) devuelve “verdadero” cuando se
llegó hasta el fnal del contenido de un archivo.
Observemos, en el siguiente ejemplo, el uso de la función feof. La condición booleana
que se usa dentro de este bucle while para seguir leyendo una letra más es que todavía “no
sea el fn del archivo”:
<?php
// Abrimos el archivo.
$abierto = fopen ("noticia.txt", " r " ) ;
Veamos ahora cómo mostrar el contenido del archivo hasta que se encuentre un ca-
racter defnido de antemano. Este ejercicio nos dará la oportunidad de aplicar otra vez el
concepto de anidar un condicional dentro de un bucle, que vimos en este mismo capítulo.
Este condicional se ejecutará una y otra vez (una vez por cada vuelta del bucle), aplicando la
evaluación de su condición al valor “actual”, el que se está leyendo en ese momento, en esa
vuelta del bucle:
<?php
$abierto = fopen ("archivo1.txt", " r " ) ;
$cadena = "";
if ($caracter!="z"){
$cadena = $cadena . $caracter;
// Vamos concatenando cada caracter, uno por
vuelta.
} else {
break;
// Si es " z " , salimos del bucle.
}
}
fclose ($abierto);
Eso es todo con fgetc. Sumamente útil para leer archivos de texto largos, completos, o
hasta cierto punto que indiquemos con algún carácter especial, pudiendo almacenar en una
variable lo leído.
Función fgets
La función fgets (obtener del archivo) es similar a fread, pero con la particularidad de que lee
exclusivamente dentro de una única línea del archivo (por lo que es habitual para leer muy
pocos caracteres, ya que para usarse en bucles es más sencillo utilizar fle), y lee la cantidad
de caracteres especifcados menos uno; (en el siguiente ejemplo, en el que usaremos como
límite un 15, leerá hasta el caracter número 14, inclusive). Si encuentra el f n del archivo, de-
vuelve hasta el último caracter que le fue posible leer.
Ejemplo:
<?php
$abierto = fopen ("textos.txt", " r " ) ;
$caracteres = fgets ($abierto,10);
fclose ($abierto);
print ($caracteres);
?>
La función fgets es la más útil cuando sólo precisamos leer unos pocos caracteres
dentro de un archivo de texto, por ejemplo, en el caso de un archivo que almacene nada más
que la cantidad de visitas a una página:
5587
Por más visitas que tengamos, siempre la cantidad de dígitos será muy poca (con ape-
nas 7 dígitos tenemos para casi 10 millones de visitas, cosa que puede llevar bastante tiempo
y, llegado el caso, podríamos modifcar muy fácilmente la llamada a fgets para pasar a leer 8,
9, o más caracteres, y seguirá funcionando con decenas o centenas de millones de visitas).
Función fgetss
La función fgetss (observemos la doble “s” al fnal) es idéntica a fgets pero omite las eti-
quetas HTML y PHP que encuentre dentro del archivo. Se usa principalmente para abrir un
archivo XML o HTML (en general, ubicado en otro servidor, puede ser una noticia, el clima
actual, etc.). Esta función se encarga de “limpiarlo” de etiquetas HTML, para luego –por ejem-
plo– aplicarle la hoja de estilos de nuestro propio sitio.
Vamos a aplicarlo en un ejemplo para entenderlo mejor:
<?php
$abierto = fopen ("clima.html", " r " ) ;
$caracteres = fgetss ($abierto,150);
print ($caracteres);
?>
Recordemos que, al igual que fgets, la función fgetss sólo lee una línea, y termina
ante el primer salto de línea que encuentra. Por supuesto, de la misma manera que hicimos
con fgetc, también podemos utilizarla dentro de un bucle, con lo cual nos permitirá recorrer
un archivo HTML o PHP completo, quitando todas sus etiquetas y quedando solamente el
texto:
Eso nos mostrará sólo los textos del archivo “pagina.html” completo, sin ninguna eti-
queta HTML.
Esta función posee un tercer parámetro que es opcional, pero es el más interesante:
nos permite especifcar cuál etiqueta no será eliminada y, por lo tanto, se mantendrá dentro
del código generado:
<?php
$abierto = fopen ("clima.html", " r " ) ;
$caracteres = fgetss ($abierto,150,"<p>");
fclose ($abierto);
print ($caracteres);
?>
fgetss ($abierto,150,"<p><li>");
Con todas estas funciones, ya estamos en condiciones de que nuestras páginas PHP
puedan leer contenidos de los archivos de texto.
(a las que también se accede haciendo clic derecho sobre el archivo desde dentro de nuestro
programa de FTP).
Figura 8-6. Permisos de escritura al archivo de texto donde escribiremos datos automáticamente.
Atención: para probar este ejercicio, es necesario que primero se construya un formula-
rio que envíe esas dos variables: nombre y email.
Código de escribe.php:
<?php
// Abrimos el archivo.
$abierto = fopen ("deposito.txt", " w " ) ;
// Cerramos el archivo.
fclose ($abierto);
?>
Código de suscripcion.php:
<?php
// Abrimos el archivo, pero esta vez para añadir.
$abierto = fopen ("suscriptores.txt", " a " ) ;
// Cerramos el archivo.
fclose ($abierto);
?>
<?php
$matriz = fle($archivo);
?>
es de esta manera porque así lo decidió la persona que creó la función fle,
ya que, de otro modo, si no le indicábamos cuál era el archivo que queríamos
leer, mal podría la función adivinar ese dato).
2. Quien creó esta función, también decidió que la función fle sería capaz de abrir
el archivo, de leer cada renglón del archivo indicado, memorizarlo y, fnalmente,
cerrarlo; es decir, defnió cuál sería la tarea que realizaría la función fle.
3. Por último, ese programador también decidió qué devolvería la función fle
como resultado de su ejecución: celdas de una matriz, por lo que se requiere
que la ejecución de la función fle no la realicemos aislada, sino que le asigne-
mos a una matriz el resultado producido por su ejecución. En consecuencia,
siempre veremos una estructura similar al llamar a la función fle: un nombre
de matriz a la que le asignamos el resultado producido por fle. Algo como:
$matriz = fle(“archivo.txt”);
Todo eso lo decidió la persona (o equipo de personas) que creó la función fle.
De este ejemplo, podemos deducir que las funciones primero se declaran y luego se
ejecutan.
Y también podemos concluir que, para declarar una función, debemos defnir cuáles
serán sus parámetros de entrada, qué tareas realizará la función y qué valor devolverá
como resultado.
<?php
mostrarMensajes();
enviarAviso($usuario);
guardarRespuesta($codigo);
?>
Normalmente, cada página PHP poseerá los tres momentos ilustrados en la Figura 9-1:
1. Entrada de datos: es el momento en el que se proporcionan datos a la pági-
na, ya sea mediante enlaces que envían variables, o formularios, o lectura de
cookies o sesiones, o cualquier otra fuente de ingreso de datos. Esta etapa
requiere que validemos la disponibilidad de los datos recibidos, para su pos-
terior utilización.
2. Proceso de datos: es donde “haremos algo” con esos datos proporciona-
dos. Por ejemplo, si nos enviaron datos de un formulario, podremos revisar
su sintaxis, quizás hasta modifcarlos y, fnalmente, guardarlos en un lugar de
almacenamiento o derivárselos a otra función para que los siga procesando.
Ésta es la parte que estructuraremos mediante funciones.
3. Resultados: de ser necesario, se generará texto y código HTML para mos-
trar al usuario. Este resultado se puede generar directamente desde dentro
de una función, o desde el punto en el que fue llamada la función.
Nuestro trabajo más “creativo” como programadores, será identifcar aquellas tareas
específcas y repetitivas, que podríamos llegar a reutilizar a lo largo de nuestro proyecto,
para así poder armar la lista de las funciones que crearemos y usaremos en cada pá-
gina de nuestro sitio.
Volvamos al ejemplo anterior: habíamos identifcado ya un par de tareas que sería con-
veniente encapsular dentro de funciones. Una era la tarea de validar la casilla de correo
proporcionada y otra era la de escribir un dato dentro de un archivo de texto. Entonces,
crearemos dos funciones a las que podríamos darles el nombre de comprobarCasilla y
escribirArchivo.
Un comentario al paso –pero importante– acerca del nombre que demos a nuestras funcio-
nes: conviene que sean verbos en infnitivo, que refejen claramente la acción que realizará
la función y, respecto a su sintaxis, sigamos las mismas reglas que para defnir variables:
sin espacios ni caracteres especiales, sólo letras minúsculas y, comúnmente, haciendo
uso de la sintaxis camel case que aprendimos, poniendo en mayúsculas la inicial de cada
palabra que no sea la primera dentro del nombre.
Una vez decididos a crear esas dos funciones, pensemos cómo quedaría estructurado
el código de la página que recibirá la casilla ingresada en el formulario.
Esa página podría seguir esta serie de pasos:
1) Verifcar si llegó el dato esperado, y si no está vacío.
2) Llamar a la función validarCasilla, para ver si es correcta la casilla ingresada.
3) Si es correcta, llamar a la función escribirArchivo para almacenar esa casilla.
4) Si pudo almacenarse, mostrar algún mensaje al usuario.
5) Si no pudo almacenarse, mostrar algún mensaje al usuario.
6) Si no es correcta la casilla, mostrar algún mensaje al usuario.
7) Si no llegó el dato esperado o está vacío, mostrar algún mensaje al usuario.
Si pasáramos lo expresado en el párrafo anterior a código, nuestra página podría ser
similar a lo siguiente:
<?php
// Primer paso: verifcamos que el dato de entrada esté
presente, no esté vacío, y lo traspasamos a una variable local
llamada $correo:
$correo = $_POST["correo"];
if( escribirArchivo($correo)==true ){
} // fn pasos 3 , 4 y 5
} // fn paso 2
} // fn paso 1
?>
Notemos que las validaciones que comprueban si está presente un dato y si no está
vacío, conviene que sean previas al momento de traspasar esos datos (como valores de los
parámetros de entrada) a una función. Esas verifcaciones deberían ser el único código “suel-
to” que contendrán nuestras páginas PHP. Todo el resto, será mejor que lo estructuremos en
llamadas a distintas funciones.
Observemos, también, que cada llamada a una función la colocamos dentro de un
condicional, para poder saber si “funcionó”, si salió bien el proceso que esperábamos que
if( comprobarCorreo($correo) ){
if( escribirArchivo($correo) ){
etc.
De hecho, será lo que haremos de ahora en más: cada vez que veamos algo envuelto
entre las llaves de un condicional, sabremos que se está preguntando si el valor devuelto por
esa expresión se evalúa como “verdadero” (true).
El objetivo de colocar dentro de un condicional la llamada a la función, es ofrecer una
respuesta o mensaje diferente al usuario en caso de éxito o de fallo de cada uno de los
pasos, y además nos da la posibilidad de poder modifcar el hilo de ejecución (si falló una
llamada a la primera función, no tiene sentido perder tiempo en llamar a la segunda). Esto sólo
es posible en funciones booleanas, es decir, que devuelven true o false como resultado de su
ejecución (pronto veremos que no todas las funciones tienen ese comportamiento).
Habiendo visto ya cómo llamar a estas dos funciones, ahora veamos cómo las defni-
ríamos, analizando qué consideraciones es bueno que nos planteemos a la hora de declarar
una función propia.
function nombre ( ) {
tareas a ejecutar
respuesta fnal;
Y este otro también podría serlo (esta vez, incluyendo parámetros dentro de los
paréntesis):
tareas a ejecutar
respuesta fnal;
<?php
function listarMatriz($matriz){
$codigo = "<ul>";
$codigo = $codigo."<li>".$valor."</li>";
$codigo = $codigo."</ul>";
return $codigo;
}
?>
Esta función así declarada nos permitirá imprimir, dentro del código HTML de una pá-
gina, los contenidos de cualquier matriz que le pasemos como argumento (parámetro) en el
momento de “llamar” a la función.
“Llamar” a la función signifca ejecutarla, hacerla funcionar con datos reales.
Deben pasársele la misma cantidad de argumentos o parámetros (son sinónimos) que
los especifcados en la declaración de la función entre sus paréntesis, y en el mismo orden
(en este ejemplo, hemos decidido que se necesitaba un solo parámetro, el nombre de la
matriz que se imprimirá).
De esta manera, se llamaría a esta función desde otro archivo, llamadas.php:
<?php
include("funciones.php");
print("<h2>Lista de Propiedades:</h2>");
// Ahora llamamos a la función para que las muestre:
print("<h2>Lista de Vehículos:</h2>");
Como ambos bloques del código anterior (la declaración y la llamada) deben estar
disponibles y ejecutarse (respectivamente) en el mismo archivo PHP que se está procesando
en el servidor, y como es común que necesitemos que una misma función esté disponible en
distintas páginas de nuestro sitio, normalmente haremos uso de un archivo externo, que
contendrá todas las declaraciones de funciones de nuestro sitio, archivo que incluiremos
luego dentro de las páginas de nuestro sitio mediante una orden include; en este caso, cum-
ple ese rol de depósito de funciones el archivo funciones.php.
Por lo tanto, el código completo de este ejemplo quedaría estructurado de esta manera:
por un lado, el archivo funciones.php con la declaración de ésta y de cualquier otra función;
por el otro, el archivo llamadas.php.
En nuestros sitios, comúnmente tendremos más de un archivo que haga un include de
nuestro archivo de funciones, para tenerlas disponibles y usarlas:
Figura 9-2. Archivo externo con declaraciones de funciones, que será incluido desde otras páginas.
En muchos códigos, veremos que los programadores se referen a este archivo externo
que contiene declaraciones de funciones como “biblioteca” de funciones e, incluso, mal tra-
ducido, “librería” de funciones (por el original en inglés: library).
Parámetros de entrada
Si volvemos a analizar nuestra función del ejemplo anterior, veremos que recibe un valor que
se le pasa en el momento en que llamamos a la función: en este ejemplo, recibe primero la
matriz “propiedades” y, luego, en la siguiente llamada, recibe la matriz “vehículos”.
Como en la declaración de la función, al lado de su nombre, entre los paréntesis, escribi-
mos una variable a la que decidimos llamar $matriz, esta variable es la que va a contener, den-
tro de la función, la matriz que sea proporcionada como argumento desde fuera de la función.
Dentro de la función no llamamos a la matriz que fue enviada desde el “mundo ex-
terior” por su verdadero nombre, ya que siempre será un nombre distinto el que
contendrá los datos allí fuera (así como en este caso eran “propiedades” y “vehículos”, le
podríamos proporcionar a la función muchas otras matrices, siempre de distintos nom-
bres). Por eso le daremos un “alias” o sobrenombre de uso interno que, en este caso,
es $matriz, y que será el nombre de variable que pondremos dentro de los paréntesis y el
que utilizaremos para referirnos a «eso que llegó» desde fuera de la función, y lo usaremos
dentro de ella para manipular ese dato.
<?php
function cuadrado($numero){
$total = $numero * $numero;
return $total;
}
$cantidad = 6;
$resultado = cuadrado($cantidad);
// Ya ejecutamos la función, $resultado almacena un 36
$resultado = cuadrado($cantidad);
podría llamarse de cualquier otra forma sin que eso modifque nada, por ejemplo:
$dato = 1234;
$resultado = cuadrado($dato);
$resultado = cuadrado(7);
y funcionaría perfectamente.
Al número que le hemos pasado entre los paréntesis, en la declaración de la función
habíamos decidido denominarlo “internamente” $numero:
function cuadrado($numero)
Por esta razón, en la “receta” paso a paso dentro de las llaves de la función, nos refe-
rimos a ese dato que llegó de afuera como $numero, y no con el nombre que tenía fuera de
la función, ya que podría ser cualquiera, nunca sabremos qué nombre tendrá el dato que le
proporcionaremos a la función, sólo es importante saber qué hacer con ese dato que nos
pasaron al llamarla.
<?php
function aumento($precio, $porcentaje){
$total = $precio + ($precio * $porcentaje / 1 0 0 ) ;
return $total
}
$resultado = aumento(12.99, 5 ) ;
// Proporcionamos la misma cantidad de datos que de
parámetros tenga la función, en este caso, dos, separados por
Por supuesto, pueden ser más de dos los parámetros de entrada, en realidad, pueden
ser todos los que precisemos:
<?php
function contarVisita(){
// aquí abrirá el archivo, leerá la cifra de
visitas, le sumará 1 , escribirá el nuevo valor, y cerrará el
archivo
}
?>
Al llamar a una función que no necesita parámetros, debemos colocar, de todos modos,
los paréntesis al lado del nombre de la función, pero vacíos, sin ningún dato entre medio (ni
siquiera un espacio en blanco):
<?php
contarVisita();
?>
Eso solo será sufciente para que la visita sea contabilizada dentro del archivo de texto.
Otro ejemplo de una función sin parámetros sería el siguiente:
Para eso, se utiliza la palabra return colocada al fnal de la función, justo antes del cierre de
sus llaves. A continuación de la palabra return, debemos colocar el valor que devolverá la
función como resultado de su ejecución. La función devolverá una sola cosa, un sólo dato
(del tipo que sea, una variable, matriz, constante, etc.), pero uno. Si dentro del código de la
función hubiera más de un return (porque se lo colocó dentro de un condicional, por ejemplo),
sólo uno de los return se ejecutará, ya que en cuanto la función ejecuta la orden return, se
“sale” inmediatamente de la ejecución de la misma y se sigue ejecutando el código exacta-
mente a continuación del punto en que fue llamada la función.
Unas veces ese producto será texto o código HTML para mostrar en una página, como
por ejemplo aquí:
<?php
function aumento($precio, $porcentaje){
$total = $precio + ($precio * $porcentaje / 1 0 0 ) ;
return $total;
}
En este caso, esta función devolverá una cifra: la que surja de la operación que realiza
con los datos de entrada, y que estaba almacenada en la variable $total. Otras veces, esa
variable contendrá un código HTML con textos, como en el caso en el que se muestre un
listado de productos, un elemento select HTML con sus options, etc.
Pero, otras veces, no será necesario mostrar nada como resultado de la ejecución de
la función (pensemos en el contador de visitas que pusimos como ejemplo unos párrafos
atrás). En ese caso, conviene que la función devuelva un valor de “éxito” o uno de “fracaso”,
según haya podido terminar sus tareas normalmente, o no. Para devolver un valor de éxito,
usaremos la constante true, y para un valor de fracaso, la constante false. Esto nos permitirá
evaluar con un condicional si la función pudo hacer su trabajo o no.
Veamos cómo, sobre la base de un ejemplo anterior, permitimos que se realice esta
validación, haciendo que nuestra función sea booleana, es decir, que su valor de retorno o
devolución sea true o false:
function escribirArchivo($casilla){
// Omitimos todos los pasos previos,
previos, y
y nos
nos
concentramos en el fnal. Una función booleana debería terminar
con un condicional:
if( fclose($abierto) ){
return true;
} else {
return false;
Al tener como únicos posibles valores de retorno true o false, podemos validar cuál de
los dos valores devolvió al momento de llamarla:
if( escribirArchivo($correo)==true ){
} else {
function verifcar($nombre,$apellido,$edad,$correo){
/* Omitimos todos los pasos previos, y nos
concentramos en el fnal que devuelve una matriz: supongamos que
hemos verifcado el primer dato ($nombre) y hemos colocado el
resultado (true o false) dentro de $ v 1 , luego hemos verifcado
el $apellido y su resultado quedó en $v2 y así: */
$resultado = array($v1,$v2,$v3,$v4);
return $resultado;
$matriz = verifcar("Juan","Pérez","34","j@perez.com");
<?php
function cuadrado($numero){
$total = $numero * $numero;
echo $total;
}
$cantidad = 6;
cuadrado($cantidad);
// Allí, donde llamamos a la función, ya se mostró su
resultado
?>
Esto nos obliga a intercalar llamadas a la función en medio de órdenes echo o print, lo
cual da por supuesto que no va a haber errores a la hora de ejecutar esa función, y elimina la
posibilidad de validar los datos.
Por ejemplo:
$cantidad = 6;
print("<p>".$cantidad.” al cuadrado e s :
".cuadrado($cantidad)."</p>");
// Mostramos el resultado
?>
En vez de eso, y tal como lo hemos mostrado en todos los ejemplos anteriores, es
mucho mejor que la función solamente vaya acumulando códigos y texto dentro de una
variable, y lo devuelva mediante return. Por ejemplo:
<?php
function cuadrado($numero){
$total = $numero * $numero;
return $total;
}
Siempre es mejor usar un return como fnal de la función, y en el lugar desde donde
llamamos a la función, podemos validar qué devolvió la función y decidir si mostramos el re-
sultado en el momento, o si no lo mostramos, o si le tenemos que aplicar algún otro proceso
a ese dato que entregó la función y pasarlo como parámetro de entrada a otra función que
tome lo que fabricó la primera función para seguir modifcándolo. Parece un detalle menor,
pero es una técnica clave.
Es mucho mejor ir acumulando textos dentro de la función (guardados en una varia-
ble), sin que la función “emita” mensajes hasta que termine su ejecución.
Veamos otro ejemplo, esta vez con abundante texto y código HTML; veamos cómo se
va acumulando (concatenando) dentro de la variable $codigo:
<?php
function armarTabla($flas){
$codigo = '<table>';
$codigo = $codigo.'</table>';
$tabla = armarTabla($_POST["$numero"]);
Cuando se ejecute esta línea de código, la variable $tabla contendrá lo mismo que
contenía $codigo adentro de la función (o sea, contiene todo el código HTML de la tabla
entera).
Ahora, tenemos la libertad de decidir qué hacer: podemos hacer un print o echo de
$tabla si nos conviene, pero además tenemos la posibilidad de pasarle a otra función todo
lo que fabricó la función armarTabla(), dándonos la oportunidad de armar una “cadena de
montaje” como en una fábrica, en la que cada función se especializa en hacer una tarea breve
y concreta, lo que ayuda muchísimo a la modularidad del código (a que sea reutilizable, mo-
dular –estructurado en módulos, bloques–).
Por ejemplo:
$decorado = decorarTabla($tabla);
Le pasamos a una supuesta nueva función denominada decorarTabla todo lo que pro-
dujo la función anterior, gracias a que lo teníamos almacenado en la variable $tabla y a que
no hicimos ningún echo ni print desde dentro de la función.
Solo nos resta ver un último tema relacionado con las funciones: el alcance de las varia-
bles dentro y fuera de las funciones.
<?php
function infacion($precio,$suba){
$precio = $precio * $suba;
global $aumento;// Estamos anunciando que nos
referiremos a una variable externa a la función
$aumento = 1.50;// Esta línea modifca la variable
externa, cada vez que sea llamada esta función
return $precio;
}
$producto1 = 100;
$aumento = 1.10; // Ésta es la variable externa, hasta aquí
vale 1.10 ya que aún no llamamos a la función
print("<p>El producto 1 vale: ".$producto1." antes del
aumento, y la variable \$aumento todavía vale:
".$aumento."</p>");
$resultado = infacion($producto1,$aumento);
print("<p>Ahora el producto 1 vale: ".$resultado."</p>");
print($aumento."</p>");
?>
Por omisión, las variables que declaramos dentro de las funciones son locales (es
decir, se pueden usar sólo dentro de la función) pero, a veces, necesitamos acceder a va-
riables que ya fueron declaradas antes de ejecutar la función y modifcarles su valor; estas
variables “externas” a la función se denominan globales. Se puede acceder a ellas desde
adentro de una función anteponiéndoles la palabra global, como lo hemos hecho con la
variable $aumento en la función infación que recién creamos.
Notemos que la modifcación a la variable global la debemos hacer antes del return,
ya que el return “sale” de la función y, por ello, deja de ejecutarse lo que viene después, y
quedaría sin modifcarse el valor de la variable global.
También podemos acceder a una variable global desde dentro de una función mediante
la matriz $GLOBALS [“nombre-de-la-variable”], ya que esta matriz almacena todas las
variables globales que se hayan declarado en ese archivo PHP antes de ejecutar la función.
Un ejemplo:
<?php
function multiplicar($numero,$otro){
$numero = $numero * $otro;
$GLOBALS ["cifraB"] = 9; // Estamos cambiando una
variable de fuera de la función
return $numero;
}
$cifraA = 100;
$cifraB = 5 ;
print("<p>El primer número vale: ".$cifraA."</p>"); //
vale 100
print("<p>El segundo número (o sea, \$cifraB) vale:
".$cifraB."</p>");// vale 5
Es bueno que sepamos que el uso de global y GLOBALS sólo para leer una variable
global es desaconsejable, ya que sería mucho mejor pasarle ese dato a la función como
parámetro (entre los paréntesis de entrada). Puesto que la idea de una función es que
debería desempeñarse como una “caja” cerrada, en la que los datos entran por sus
«puertas» (parámetros) y salen por su return.
Hemos llegado al f n de lo que necesitamos saber para crear nuestras propias funciones.
De ahora en más, todos nuestros códigos podrán ser organizados mediante funciones
propias, creadas por nosotros para que realicen todas las tareas específcas que necesite-
mos y listas para ser reutilizadas a lo largo de todos nuestros futuros proyectos.
que utilizaron esa función junto con sus experiencias relacionadas con ella (encontrarán esto
último al pie de cada página, en el listado de comentarios de usuarios).
Función trim
La función trim (recortar, limpiar) elimina cualquier caracter de control, tanto al principio
como al fnal de una cadena de caracteres. Suprime toda esta lista de caracteres:
“\t” Tabulador
“\n” Nueva línea
Un ejemplo:
<?php
$cadena = "\tabcd \ n " ;
$limpio = trim($cadena);
print ($limpio);
// Escribe "abcd", sin tabulador ni espacios ni salto de
línea.
?>
Función ltrim
La función ltrim (letf trim o limpiar a la izquierda) elimina los caracteres de control (espacios,
tabuladores, nueva línea, etc.) que hubiera al principio (a la izquierda) de la cadena de
caracteres, pero no los del fnal.
Atención: en ninguno de los dos casos se eliminan caracteres de control ubicados “en
medio” de la cadena de texto, sólo al principio y al fnal.
Para eso nos sirven las funciones strtolower (string to lower case, o texto a minúsculas)
que lleva el texto a minúsculas, y strtoupper (string to upper case, o “texto a mayúsculas”),
que convierte todos sus caracteres en mayúsculas.
Veamos un ejemplo:
<?php
$claves = fle("claves.txt");
$cuantos = count($claves);
$encontrado = "no";
if ($encontrado == "no"){
include ("error.php");
} else {
include ("secreto.php");
}
?>
<?php
function verifcarLongitud($cadena,$maximo){
if (verifcarLongitud($_POST["comentario"],200)){
echo "Correcto";
} else {
echo "La longitud ingresada supera el máximo de 200
caracteres...";
}
Función substr
La función substr (substring o subcadena) se utiliza para obtener parte de una cadena de
texto. Se deben especifcar tres argumentos:
1. cuál es la cadena,
2. a partir de cuál caracter queremos obtener,
<?php
$texto = "Este es un curso de PHP";
$inicio = 5 ;
// Los caracteres se numeran desde cero
$parte = substr($texto, $inicio);
echo $parte;
// Mostrará: "es un curso de PHP", es decir, desde el
caracter 5 hasta el fnal del string.
?>
Los caracteres que queremos leer se cuentan a partir de cero, por esta razón, la “e”
que ocupa el sexto lugar en la cadena (el [5], recordemos que el primero es el [0]) se toma
como inicio de la parte deseada.
En cambio, si especifcamos el tercer argumento, podremos recortar una parte desde
un inicio hasta una cantidad específca de caracteres:
<?php
$texto = "Esta es una parte del string";
$inicio = 1 2 ;
$cuantos = 5 ;
$parte = substr($texto, $inicio, $cuantos);
echo $parte;
// Mostrará: "parte".
?>
Si el punto de inicio es negativo, se cuenta de atrás para adelante hasta llegar a ese
punto inicial. Luego se seleccionarán los caracteres que siguen hacia el fnal, normalmente:
<?php
$cadena = "www.sitio.com.ar";
$sitio = substr($cadena,-7,7);
print($sitio);
// Mostrará ".com.ar"
?>
Si el punto de inicio es positivo, pero el largo es negativo, esos dos caracteres se con-
siderarán el punto de inicio y el punto de fnalización (se permite la selección de un fragmento
del que no conocemos la longitud, pero sí la cantidad de caracteres previos y posteriores); por
ejemplo, podemos extraer el nombre del dominio a partir de un dato ingresado de la siguiente
manera:
<?php
$direccion = "www.pagina.com.ar";
$sitio = substr($direccion,4,-7);
print($sitio);
// Imprimirá "pagina"
?>
Función strpos
Conoceremos ahora la función strpos (string position o posición de una cadena). Esta función
sirve para saber en qué posición, dentro de una cadena de caracteres, aparece por primera
vez un caracter o cadena de caracteres buscados.
Sus argumentos son: la cadena de texto dentro de la cual buscar, y el caracter o ca-
racteres de los que se quiere conocer la posición.
Ejemplo:
<?php
$cadena = "América Latina unida";
$abuscar = "unida";
$posicion = strpos($cadena,$abuscar);
print($posicion);
// Imprimirá 15 -comienza desde cero-.
?>
Pensemos ahora en los usos que le podemos dar a la función strpos. El truco para
usarla en búsquedas y validaciones consiste en preguntar con un if si esa posición es distinta
de “false, cero o vacía”, lo que signifcará que el texto sí fue encontrado.
Debido a esa relativa complejidad en el dato que puede llegar a devolver esta función,
necesitaremos utilizar un operador de comparación que no vimos antes: el de identidad, que
consiste de un triple signo igual ===, y que evalúa no sólo que los valores comparados sean
iguales, sino que, además, únicamente devuelve verdadero si, además de ser iguales, ambos
valores comparados son del mismo tipo de dato (cadena de caracteres, entero, booleano,
etc.). De esta manera, podremos diferenciar la situación de no haber encontrado “algo”, que
<?php
$cadena = "América Latina unida";
$texto_buscado = "A";
$posicion = strpos($cadena,$texto_buscado);
if( $posicion===false ){
echo "No se encontró";
} else {
echo "Sí se encontró, en la posición: $posicion";
}
?>
<?php
function permitirLetras($cadena){
$letras =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$longitud = strlen($cadena);
if(strpos($letras,substr($cadena,$i,1))===
false ){
// $cadena no es válido
return false;
}
}
// $cadena es válido
return true;
}
}
// $cadena es válido
return true;
}
if( permitirLetras("Pepé") ) {
echo "Correcto";
} else {
echo "Utiliza caracteres prohibidos";
?>
El punto clave está en extraer letra a letra de la cadena con substr($cadena,$i,1), que
va leyendo, en cada vuelta del bucle, una letra diferente de lo escrito por el usuario, ya que
cambia el caracter de comienzo proporcionado por $i.
Entonces, en cada vuelta del bucle, se comprueba si esa letra escrita por el usuario se
encuentra dentro del texto de caracteres permitidos. La lógica de esta comparación permite
que la modifquemos fácilmente para incluir en la variable $letras aquellos caracteres que con-
sideremos válidos (podrían ser los números del 0 al 9 para validar campos numéricos, o incluir
letras, números y guiones para campos alfanuméricos, o acentos, eñes, etc.).
Función strstr
La función strstr devuelve como resultado toda la cadena de texto hasta su fnal, a partir del
caracter especifcado.
Por ejemplo:
Puede especifcarse un tercer argumento, opcional, que invierte el sentido hacia el cual
captura un segmento de texto: en lugar de ir desde el carácter buscado hasta el fnal de la
cadena, en este caso, captura desde el inicio de la cadena hasta el carácter indicado.
Veamos un ejemplo:
<?php
$email = "casilla@dominio.com.ar";
$caracter = " @ " ;
$dominio = strstr($email,$caracter,true);
print($dominio);
// Imprimirá "casilla"
?>
remos en su forma más elemental. Por esta razón, invitamos al lector a que investigue más
acerca de ella).
<?php
/* Suponemos que venimos de un formulario donde el usuario ya
completó su dirección en la variable $email
*/
if ( preg_match("/@/", $email) ){
print ("<p>Casilla correcta</p>");
} else {
print ("<p>A su casilla le falta la arroba</p>");
}
?>
$prohibido = "tonto";
if ( preg_match("/$prohibido/i", $comentario) ){
print ("No se permite esa palabra. Escriba su
comentario con mayor cortesía");
} else {
print ("Gracias por su comentario");
}
?>
Notemos, luego del cierre de la barra fnal que envuelve lo que buscamos, la presencia
del modifcador i (de ignore, ignorar diferencias de mayúsculas o minúsculas). Este modif-
if ( preg_match("/\b$prohibido\b/i", $comentario) ){
Pero ahora será cuando se revele la verdadera potencia de las expresiones regulares: si
lo que queremos es encontrar si los caracteres pertenecen a un rango determinado, pode-
mos envolver ese rango entre corchetes, separando el valor inicial y fnal con guiones. Por
ejemplo, si el valor permitido para cada dígito de un campo son sólo números presentes en el
rango que va del 0 al 9, lo podemos expresar de la siguiente manera:
if ( preg_match("/[^0-9]/", $numero) ){
Del mismo modo, es posible validar que el texto contenga únicamente letras de la a a
la z:
if ( preg_match("/[^a-z]/", $numero) ){
<?php
$casilla="pepe@deja espacio.com";
if ( flter_var($casilla,FILTER_VALIDATE_EMAIL)){
} else {
?>
<?php
?>
usuario1:clave1
usuario2:clave2
Pepe|Perez|24|Soltero|Calle 1|234|3ro|A|
Carlos|Garcia|36|Casado|Calle 3|456|1ro|B|
<?php
$flas = fle("usuarios.txt");
$cuantos = count($flas);
}
?>
Otro uso común de explode es contar palabras de un texto (cargando el texto entero
en una matriz, usando como divisor el espacio en blanco entre palabras, y luego contando
las celdas de esa matriz).
Ahora, la acción contraria: podemos tomar diferentes datos, de cualquier origen –por
ejemplo, de distintos campos de un formulario– y unirlos en una única línea –lo que equivale
a “pegar” partes o piezas–, intercalando entre parte y parte un caracter que haga de separa-
dor. Un ejemplo de la utilidad de esto es guardar en un solo renglón de un archivo de texto
un conjunto de datos relacionados (es decir, “fabricar” un registro completo, similar a los que
utilizamos en estos últimos ejercicios).
<?php
/* Suponemos que el usuario completó sus datos en la página
anterior, y se almacenaron en las variables $nombre, $email y
$comentario */
$datos = array($nombre, $email, $comentario);
print ($unido);
?>
Si luego almacenamos ese texto en algún archivo de texto (o base de datos) cuando
más adelante deseemos leerlo, veremos que no se visualizarán los enters escritos por el
usuario. Esto sucede porque los \n para HTML no signifcan lo mismo que en los casos en los
que se encuentran dentro de un archivo de texto plano (en el archivo HTML generan saltos de
línea en el código fuente, no en la pantalla).
Por ejemplo, el código anterior mostrado dentro de un archivo HTML con un echo o
print generará lo siguiente dentro del código fuente:
[…]
<body>
Hola
Estoy consultando por el producto publicado. Mi teléfono es
4444-4444.
Agradeceré su llamado.
Como observamos, los saltos de línea no se ven en el navegador. Pero podemos so-
lucionar esta pérdida causada por el cambio de formato desde texto plano a código HTML,
convirtiendo, con la función nl2br (new line to break o Nueva línea a break), cada uno de los
saltos de línea en una etiqueta <br /> de HTML, justo antes de guardar el texto generado por
el usuario dentro de una base de datos o archivo de texto plano.
Al código del ejemplo anterior, suponiendo que llega de un formulario en un campo
denominado “comentario”, lo procesaríamos de la siguiente manera:
<?php
$formateado = nl2br($_POST["comentario"]);
echo $formateado;
?>
[…]
Hola<br />
Estoy consultando por el producto publicado. Mi teléfono es
4444-4444.<br />
Agradeceré su llamado.<br />
Saludos<br />
Juan Pérez.
De esta manera, ahora sí mostrará en el navegador cada frase en una línea distinta, tal
como el usuario la escribió en el campo de texto. Si nuevamente debiéramos almacenar este
código en un archivo de texto plano, podríamos utilizar una de las recientemente aprendidas fun-
ciones de búsqueda y reemplazo, buscando cada <br /> y reemplazándolo otra vez por un “\n”.
Caracter a
El resultado quedará del tipo:
colocar:
% Un caracter literal de porcentaje. No se precisa argumento.
b El argumento es tratado como un entero y presentado como un número binario.
El argumento es tratado como un entero, y presentado como el caracter con
c
dicho valor ASCII.
Caracter a
El resultado quedará del tipo:
colocar:
d El argumento es tratado como un entero y presentado como un número decimal.
El argumento es tratado como un doble y presentado como un número de coma
fotante.
El argumento es tratado como un entero, y presentado como un número octal.
El argumento es tratado como una cadena de caracteres (string) y es presentado
como tal.
El argumento es tratado como un entero y presentado como un número
hexadecimal (minúsculas).
El argumento es tratado como un entero y presentado como un número
X
hexadecimal (mayúsculas).
Cuadro 10-2. Los tipos de dato posibles de printf y sprintf
<?php
// Supongamos que tenemos almacenados en variables un día,
mes y año.
$fecha = sprintf("%02d-%02d-%04d", $dia, $mes, $anio);
?>
<?php
$importe1 = 25.55;
$importe2 = 15.15;
Seguiremos utilizando, a lo largo del libro, estas funciones para trabajar con cadenas
de caracteres. En caso de necesidad, podemos seguir investigando las cerca de 100 fun-
ciones que posee esta categoría de manejo de caracteres, en el manual ofcial de PHP:
http://ar.php.net/manual/es/ref.strings.php
<?php
$ahora = time();
print ($ahora);
?>
Si creamos una página con este código y actualizamos la página varias veces en el
navegador, veremos cómo, cada vez que la ejecutamos, se va incrementando el número (ya
que la cantidad de segundos transcurridos desde el 01/01/1970 hasta el momento actual
cada vez es mayor).
Si queremos hacer operaciones, como por ejemplo, calcular un plazo de dos horas
a partir del momento actual, podemos sumarle la cantidad de segundos necesaria (lo
mismo vale para restas, multiplicaciones o divisiones: siempre la unidad de medida son los
“segundos”):
<?php
$ahora = time();
$dosHorasMas = $ahora + 7200;
/* 60 segundos cada minuto, por 120 minutos que tienen las
dos horas, da 7200 segundos */
print ("El plazo vence en: ".$dosHorasMas." segundos");
?>
Hora
“hours”
Minutos
“minutes”
Segundos
“seconds”
Día del mes, en número “mday” (month day)
Mes, en número
“mon”
Año, en número
“year”
Día de la semana, en número (comienza en “0” para el
“wday” (week day)
domingo, “1” para lunes, etc. y llega hasta el “6” -sábado-)
Días transcurridos desde el principio del año, en número “yday” (year day)
<?php
$ahora = time();
$detalle = getdate($ahora);// Convirtió a $detalle en una
matriz con las diez celdas que acabamos de mencionar
Todo el conjunto de caracteres dentro de los paréntesis de la función date debe envol-
verse entre comillas.
<?php
print (date("d-m-Y")); // Observar el separador "-"
?>
El siguiente ejemplo daría un error, ya que las d imprimirán el número del día cada vez
que aparecen, y la l mostrará el día de la semana.
<?php
print ("Hoy es ".date("d de m del Y " ) ) ;
?>
Una solución sería concatenar tramos de texto con tramos en los que ejecutamos la
función date:
<?php
print ("Hoy es ".date("d")." de ".date("m")." del
".date("Y"));
?>
Además de usarse sin especifcar ningún valor de timestamp (con el valor por defecto,
que es el momento actual), como en estos ejemplos, a la función date también se le puede
especifcar, como segundo parámetro, un valor de timestamp.
<?php
$hora = date("H:i:s",1451606399);
echo $hora;
?>
Zonas horarias
Pero, a veces, puede sucedernos que el valor de timestamp que le hemos proporciona-
do, sea interpretado con alguna diferencia horaria, debido a que el archivo de confguración
php.ini de nuestro servidor o hosting tenga defnida una zona horaria diferente a la nuestra o
a la del público mayoritario de nuestro sitio.
Podemos corregir este desfasaje de dos maneras:
1. Localmente, editando el archivo php.ini y buscando esta parte:
[Date]
; Defnes the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = America/Argentina/Buenos_Aires
Allí podemos especifcar el código de la zona horaria según nuestra ubicación. La lista
completa de zonas horarias que se utiliza como valor de “date.timezone” se encuentra en:
http://www.php.net/manual/es/timezones.php
2. En un hosting, si bien no podremos editar el archivo php.ini, sí ejecutaremos la
función date_default_timezone_set, que requiere, como parámetro, que le propor-
cionemos la misma cadena de caracteres que en el caso anterior.
Veamos un ejemplo:
<?php
date_default_timezone_set('America/Argentina/
Buenos_Aires');
?>
A partir de ese momento, pero sólo durante la ejecución de esa página, estará vigente la
zona horaria defnida.
Suele ocurrir que, en ciertos países, en algunos años se decide cambiar el horario en
alguna temporada, atrasando o adelantando una o más horas arbitrariamente. Para corregir
esto, tendremos que crearnos una función propia que modifque todas las fechas que va-
yamos a utilizar, sumándole (o restándole) al valor de timestamp la cantidad de segundos
necesarios (3600 segundos en el caso de una hora).
Atención: reiteramos que en esta función el mes va antes del día, como se escribe en
Norteamérica.
<?php
$navidad = mktime(23,59,59,12,24,2020); // No lleva
comillas
print("La navidad de 2020 sucederá en el instante:
".$navidad);
?>
<?php
$primera = checkdate(12,32,2020);
De esta forma, terminamos nuestro recorrido por las principales funciones de manejo de
fecha y hora que trae predefnidas el lenguaje PHP. Si necesitamos consultar la totalidad de
funciones agrupadas bajo esta categoría (cerca de cincuenta funciones), podemos hacerlo,
como siempre, en el manual ofcial de PHP:
http://ar.php.net/manual/es/ref.datetime.php
Atención: Para que todos estos ejemplos puedan funcionar, es preciso disponer de un
servidor Web con un programa servidor de correos confgurado y con acceso a internet,
en caso contrario, no podrá enviarse ningún mensaje.
Es común que los hostings tengan un servidor de correos habilitado, por lo que lo ideal
es probar estos ejercicios en un hosting real (deberíamos tener contratado uno con PHP y
MySQL).
En el caso de una PC hogareña con un servidor local, deberemos instalar un servi-
dor de correos (para Windows recomendamos MDaemon o Mercury y, bajo Linux, Postfx o
Sendmail). Como la confguración de un servidor de correos es un tema técnico que puede
ser bastante complejo, que excede largamente el alcance de este libro y compete más bien a
administradores de sistemas operativos, buscaremos ayuda para confgurarlo en la Web del
servidor de correo que elijamos instalar.
Envío básico
En capítulos anteriores, hemos aprendido a “recibir” la información que el usuario escribe en
un formulario, leyéndola en las matrices $_GET o $_POST, y la hemos utilizado en la siguiente
página. Pero, hasta ahora, simplemente nos limitamos a mostrar lo que el usuario elegía o
escribía, o lo hemos almacenado en un archivo de texto.
Vamos a aprender cómo enviar esos datos hacia una casilla de correo electrónico de
destino. Este envío será realizado automáticamente cuando ejecutemos la función mail de
PHP: en ese momento, el software intérprete de PHP solicitará al servidor de correos especi-
fcado en el archivo de confguración php.ini que realice el envío y, si este programa servidor
de correos logra realizarlo, la función devolverá true; de lo contrario, si falla, false.
La función mail de PHP necesita que le pasemos como mínimo los siguientes tres
parámetros para funcionar:
1 . La casilla de destino a la que debe enviarse el correo.
2. El asunto (subject) del correo.
3. El contenido o cuerpo del correo.
Existe la posibilidad de defnir un cuarto parámetro de esta función destinado a agre-
gar cabeceras del protocolo SMTP (Simple Mail Transfer Protocol, o Protocolo Simple de
Transferencia de Correo) pero, como es opcional, lo veremos unos párrafos más adelante.
Esta función mail, además de realizar la tarea de envío de un correo, es una función
booleana, por lo que devuelve con su return un true o false, que es muy útil para validar den-
tro de un condicional si se pudo enviar el mensaje o no.
Podríamos pensar, sobre la base de nuestros conocimientos adquiridos hasta aquí, que
bastaría con armar un formulario en el que el usuario fuese quien escriba estas tres cosas,
en dos campos de texto y un área de texto (textarea), generando esas tres variables (casilla
de destino, asunto y mensaje), para que, en la página siguiente, las usemos como paráme-
tros de la función mail, pero... esto sería sumamente peligroso en un sitio Web real, ya que
el remitente de esos mensajes enviados será el programa servidor de correos de nuestro
hosting; imaginemos que los usuarios podrían enviar correo basura (SPAM) ya que el remi-
tente somos nosotros (nuestro servidor, nuestra dirección IP perfectamente individualizable,
lo que puede costarnos bastante dinero si el NIC decide penalizar y bloquear esa dirección IP,
que inmediatamente dejaría inactivos a cientos de sitios Web alojados en el mismo servidor).
Para evitar este problema, no permitiremos que el usuario escriba alguno de esos tres
argumentos. Imaginemos los casos:
1. Un formulario donde el usuario nos hace una consulta (al dueño del sitio). En
este caso, pondremos la dirección de destino de forma fja, defniéndola dentro
de una variable, y quien escriba no verá nunca hacia qué dirección sale enviado el
correo, y sobre todo, no podrá cambiarla. Sí podrá especifcar un asunto (si lo
consideramos necesario, si no, lo defnimos también nosotros) y eso sí, un cuerpo
del mensaje.
2. Un formulario para recomendar nuestro sitio. En este caso, saldrá un correo des-
pachado hacia la dirección de destino que el usuario elija (la de su “amigo”), pero
el texto del mensaje y el asunto los escribiremos nosotros como dueños del sitio.
A lo sumo, dejaremos que el usuario agregue un comentario, pero acompañado de
una advertencia de que el mensaje fue enviado automáticamente.
Es decir, que siempre “desactivaremos” las combinaciones peligrosas.
Casos prácticos
A continuación, aplicaremos la función mail en dos casos prácticos: el típico formulario de
consultas que todo sitio posee y el formulario que permite recomendar una página a un
amigo. Por supuesto que a medida que avancemos en el aprendizaje de PHP, se nos ocurri-
rán muchos otros usos prácticos de la función mail, en especial cuando hayamos aprendido
a interactuar con bases de datos.
Formulario de consultas
Dentro del cuerpo de una página llamada consultas.html, agregaremos lo siguiente:
Este formulario defne dos variables (“asunto” y “mensaje”), que estarán disponi-
bles en la página de destino (a la que llamaremos respuesta.php), dentro de las celdas:
$_POST[“asunto”] y $_POST[“mensaje”].
La página respuesta.php contendrá esto (desde ya que es aconsejable validar que ha-
yan sido enviadas las variables esperadas, y que no estén vacías, pero eso lo dejamos para
aplicarlo por nuestra cuenta):
<?php
$destino = "micasilla@misitio.com";
La función mail necesita que le pasemos exactamente en ese orden los tres parámetros
o argumentos: el primero, debe ser una dirección de correo electrónico (en este caso, la
tomamos de la variable $destino, que no se la dejamos defnir al usuario sino que la llenamos
con un valor nosotros mismos); segundo, el asunto del correo, que lo tomamos de la celda
“asunto” de la matriz $_POST; y, fnalmente, el cuerpo del mensaje, que lo leemos de la celda
“mensaje” de $_POST.
<label>Enviar datos:
<input type="submit" value="Enviar" />
</label>
</feldset>
</form>
<?php
$asunto = $_POST["nombreAmigo"].": ".$_POST["nombreSuyo"]." te
recomienda visitar www.sitio.com.ar";
Un detalle: podemos ejecutar más de una vez, por ejemplo, dos veces la función mail,
logrando que le llegue un mensaje al “amigo” y otro correo a nosotros, conteniendo los datos
de ambos, de quien envió y de quien recibió la recomendación (puede ser interesante para
armarnos una lista de suscriptores):
Incluso, sería interesante ejecutar por tercera vez la función mail, para que al “recomen-
dador” le llegue un mensaje de agradecimiento (poniendo su casilla como destino, en el pri-
mer parámetro, y preparando un par de variables con los textos específcos que le enviaremos
en el asunto y en el cuerpo del mensaje).
Ya que al pasar nos hemos referido a la cantidad de veces que ejecutamos la función
mail, seamos conscientes de que podemos incluso ejecutarla “a repetición”, dentro de un bu-
cle, por ejemplo, para enviar un mismo mensaje a toda una lista de destinatarios almacenada
en un archivo de texto o en una base de datos.
<?php
$asunto = $_POST["nombreAmigo"].": ".$_POST["nombreSuyo"]." te
recomienda visitar www.sitio.com.ar";
Nota para curiosos: para conocer cuáles son las cabeceras más comunes (Cc, Bcc,
etc.) del protocolo SMTP (el que utilizan los servidores para enviar correos electróni-
cos) sólo tenemos que abrir con nuestro programa lector de correo electrónico (Outlook,
Thunderbird) el “código fuente” de un mensaje, y mirar las cabeceras.
\r\n
(una barra hacia la izquierda –el Alt 92 del teclado numérico– y una r de Return, luego otra
barra hacia la izquierda y una n de Newline, o nueva línea).
Por ejemplo:
Al recibir este mensaje en un programa lector de correos, se verá un renglón debajo del
otro, por obra de los \r\n, visualizándose el mensaje de la siguiente manera:
Notemos que comienza una nueva línea cada vez que colocamos entre comillas dobles
un \r\n.
<?php
$destino = "alguien@sitio.com";
La función mail será muy útil cuando armemos sistemas completos, con bases de da-
tos, ya que será la forma más directa de que nuestros sistemas se mantengan comunicados
automáticamente con los usuarios registrados, enviando noticias, mensajes, cambios de con-
traseñas, etc. muy fácilmente.
Vamos a aplicar ahora varias de las funciones aprendidas en este capítulo, no solo de
envío de correos sino de manejo de cadenas de caracteres, para crear una función propia que
impida que utilicen nuestros formularios para el envío de SPAM.
Nos concentraremos en que nuestra función detecte, en cada campo donde pueda es-
cribir el usuario, si está presente cierta cadena de caracteres que consideremos “riesgosa”,
ya que potencialmente podría agregar cabeceras SMTP a nuestro envío, con la posibilidad
de que en vez de un sólo envío, un spammer realice varios envíos de su texto a distintas
direcciones, gracias a la cabecera Bcc.
Veamos cómo podría ser esta función:
<?php
function validarDatos($campo){
// Matriz con las posibles cabeceras a utilizar por
un spammer
$cabeceras = array("Content-Type:",
"MIME-Version:",
"Content-Transfer-Encoding:",
"Return-path:",
"Subject:",
"From:",
"Envelope-to:",
"To:",
"bcc:",
"cc:");
/* Ahora comprobamos que entre los datos no se encuentre alguna
de las cadenas de la matriz. Si se encuentra alguna de esas
cadenas, se muestra un mensaje */
if ($bandera == "no"){
return false;
} else {
return true;
}
}// Cierra función
?>
if ( isset($_POST["nombre"]) ){
if (!validarDatos($_POST["nombre"]) ){
echo "<p>ATENCION: Detectamos que se está
intentando enviar caracteres no permitidos dentro
del Nombre.</p>";
}
Con esto, ya estamos en condiciones de seguir explorando por nuestra propia cuenta,
en el manual ofcial de PHP, el resto de las funciones predefnidas que nos ofrece este
lenguaje, y de utilizar las funciones de manejo de caracteres, de fecha y hora, y de envío de
correos en nuestros próximos trabajos que, a partir del capítulo siguiente, integrarán la enor-
me potencia de las bases de datos.
Figura 11-1. El intérprete de PHP solicita a MySQL datos, y los muestra en una página.
Figura 11-2. El intérprete de PHP envía datos a MySQL para que los almacene.
Base de datos
Nuestro gestor de bases de datos MySQL nos permitirá crear tantas bases de datos como
proyectos necesitemos (y como espacio tengamos en nuestro disco rígido, o en el hosting
que utilicemos).
Conceptualmente, una base de datos es un “paquete” que contiene toda la informa-
ción necesaria para el funcionamiento de un sistema o proyecto completo. Por ejemplo, una
base de datos llamada “tienda” puede almacenar todos los datos de un sistema de comercio
electrónico (incluyendo datos sobre los productos, las ventas, el inventario, la facturación,
las formas de pago, las formas de envío, etc.). Cada base de datos es un almacén donde se
guarda información sobre un conjunto completo de información relacionada, necesaria
para que un sistema completo funcione.
Físicamente, cada nueva base de datos en MySQL crea un directorio o carpeta que
contendrá los archivos de datos de esa base. Al igual que sucede en la relación entre carpetas
y archivos, por sí sola, la base no signifca nada, es similar a una carpeta, un simple conte-
nedor. Lo que guarda la información son los objetos que tiene almacenados adentro. Pues
bien: la información dentro de las bases de datos se guarda en tablas (las bases de datos son
simplemente conjuntos de tablas).
Tablas
Volviendo al ejemplo de la base de datos de una “tienda”, esta base podría contener las si-
guientes tablas:
• productos,
• categorías,
• usuarios,
• pedidos,
• envíos,
• pagos.
Es decir, cada uno de los conceptos sobre los cuales necesitamos guardar datos co-
rresponderá a una tabla. Por ejemplo, crearemos una tabla para los “productos”, ya que la
información que tenemos acerca de cada producto comparte una misma estructura: tendre-
mos un nombre para cada producto, una descripción, un precio, una cantidad disponible, etc.
Todos los contenidos de una misma tabla deben compartir la misma estructura.
Campos
La estructura de una tabla se defne por la cantidad de campos en que fraccionemos la
información que guarda. Los posibles campos (podemos imaginarlos como “columnas” de
una planilla de cálculo) para una tabla de –por ejemplo– “productos”, podrían ser el código de
producto, el nombre del producto, su descripción, la categoría a la que pertenece, el precio,
etc. Cada campo tendrá defnido un tipo de dato que limitará lo que podrá almacenarse en
él (datos numéricos, alfanuméricos, fechas, etc.) y, también, le defniremos a cada campo una
longitud máxima (el “ancho” de la columna, siguiendo el ejemplo de una planilla); es decir, la
cantidad máxima de caracteres que prevemos almacenar en ese campo.
Registros
Cada ítem de esa tabla (cada “producto”, en el ejemplo anterior) se almacenará en un regis-
tro (una fla horizontal, un renglón).
Cambiemos de ejemplo, y veamos los elementos de una tabla dedicada a almacenar
“mensajes” que los usuarios enviaron mediante un formulario:
Lo que vemos en la primera fla (los títulos en negrita) representan lo que sería la estruc-
tura de la tabla: en este caso, qué información se guardará relativa a cada “mensaje” (ya que
estamos ante una tabla llamada “mensajes”).
En el ejemplo, hemos decidido estructurar la información en cuatro columnas: “id”,
“nombre”, “email” y “mensaje”. A estas columnas se las denomina campos (se dice: el cam-
po “id”, el campo “nombre”, el campo “email” y el campo “mensaje”):
La fla 2 (el segundo registro) tiene los datos del mensaje de García:
y así sucesivamente.
Entonces, en resumen:
• una base de datos contiene una o más tablas,
• una tabla se estructura en campos (columnas),
• cada fla o renglón se llama registro.
Ya fjaremos estos conceptos a medida que los sigamos ejercitando.
Figura 11-3. Debemos pulsar ambos botones, uno para encender el servidor Web Apache, y otro para
MySQL.
Figura 11-4. Una vez encendidos, veremos la palabra Running con fondo verde.
O también podemos pulsar el botón de acceso directo que dice Admin a la altura del
renglón de MySQL en el panel de administración del XAMPP:
Seguridad
Llegados a este punto, en el que vamos a comenzar a utilizar bases de datos, es buen mo-
mento para que le demos una mayor seguridad a nuestra instalación local ya que, hasta
ahora, no hemos protegido dos puntos críticos:
1. Cualquier persona que conozca o adivine nuestra dirección IP, puede navegar por
las páginas que sirve nuestro servidor Web local, incluyendo el phpMyAdmin (por
esta razón, podría borrar o leer todas nuestras bases de datos); esto se remedia
defniendo un usuario y clave para ingresar al servidor local con un navega-
dor (tendremos que ingresarlos cada vez que queramos probar nuestros archivos
localmente).
2. Debemos cambiar la contraseña del usuario llamado “root”, que tiene permi-
sos de administrador en el programa MySQL, y que, por ahora, está vacía (no tiene
ninguna contraseña aún).
Podemos realizar estas dos tareas muy fácilmente desde la página inicial del XAMPP,
entrando a:
Figura 11-7. Enlace de acceso a confgurar niveles de seguridad en nuestro servidor local.
Una vez que entremos, veremos que esa página PHP realiza una serie de comprobacio-
nes, resaltadas en color rojo, amarillo o verde según su riesgo:
I XAMPP L73 - Morilla Firefox
- C ni | [ 3 1 htip:/A>cahost/security/
Los puntos marcados en verde están seguros; los puntos en rojo son
definitivamente inseguros y en los amarillos no se pudo comprobar la
seguridad (por ejemplo porque el programa a comprobar no estaba en
marcha).
|<hr> [ I ? * » ; Ü Terminado
Para solucionar todo esto, en la página del chequeo, el XAMPP nos proporciona un
enlace al que deberemos entrar:
http://localhost/security/xamppsecurity.php
Luego, seguiremos las instrucciones en pantalla.
Atención: es crítico que anotemos, en un lugar seguro, estos datos (usuarios y cla-
ves), ya que, de lo contrario, no podremos ingresar más al servidor local y deberíamos
reinstalarlo.
Este enlace abrirá una pantalla que, ante todo, nos pedirá que le asignemos una clave
al usuario “root” de MySQL. Colocamos la clave que deseemos (para ejemplo, vamos a su-
poner que escribimos la palabra “clave”), y la repetimos, y dejamos marcadas las opciones
que aparecen por defecto:
Pulsamos el primer botón gris que dice Password changing, que nos pedirá que apa-
guemos y encendamos nuevamente MySQL (lo hacemos desde el panel de control del XAM-
PP, pulsando Stop a la altura del renglón correspondiente a MySQL, y, luego, nuevamente
Start).
Después, pasaremos a la parte inferior de esa pantalla y defniremos una clave de
acceso para entrar con el navegador a las páginas servidas por nuestro servidor Web local,
nuestro localhost. En este caso, hemos colocado un usuario llamado “abrete” y una clave
“sesamo”, y pulsamos el botón gris al fnal de la pantalla, que dice Make safe the XAMPP
directory.
Figura 11-10. Desde ahora, deberemos ingresar nuestro usuario “abrete” y la clave “sesamo” para
entrar a localhost.
Nos indica que los datos de acceso fueron guardados en dos lugares:
C:\servidor\xampp\security\xampp.users
C:\servidor\xampp\htdocs\xampp\.htaccess
Una vez confgurado todo esto, estamos listos para trabajar con bases de datos de una
manera físicamente segura, que impida el acceso a nuestros datos. Anotemos estos usuarios
y claves, ya que continuamente los necesitaremos para poder interactuar con nuestras bases
de datos.
Por supuesto, esta operación que realizamos localmente, en un hosting ya se han ocu-
pado de hacerla, por lo que sólo deberemos conocer la URL de acceso al phpMyAdmin, y
el usuario y clave de MySQL (ya no será “root” ese usuario, sino otro que podremos crear
desde algún panel de administración de los servicios del hosting, que deberemos consultarlo a
la empresa de hosting que contratemos, ya que en cada empresa el proceso y las herramientas
pueden variar, incluso en algunos hostings, ellos crearán nuestro usuario y clave para MySQL).
Regresando a nuestro servidor local, si ahora volvemos a ingresar a:
http://localhost/security/
veremos que los puntos de chequeo esta vez ya fueron dados por aprobados, y los observa-
mos en color verde (o amarillo para los que no se aplican, como el servidor de FTP y Tomcat,
que no necesitamos activar).
Atención: las bases de datos que estamos viendo enumeradas a la izquierda de nuestro
phpMyAdmin, llamadas “cdcol”, “information_schema”, “mysql”, “phpmyadmin” y “test”,
que vienen preinstaladas, y que contienen las tablas necesarias para el funcionamiento
de MySQL y de phpMyAdmin, son bases de datos demasiado importantes como para
que corramos el riesgo de borrarles o modificarles algún dato por accidente, ya que
guardan la configuración y los permisos de todos los usuarios de nuestro servidor
local, por lo cual, en caso de modificarlas o borrarlas, no podremos utilizar más MyS-
QL y deberemos reinstalar los programas. ¡No toquemos esas bases! (de hecho, en
un hosting ni siquiera nos permitirán visualizarlas, son patrimonio del administrador
del hosting).
Para crear una nueva base de datos, dentro del phpMyAdmin escribiremos (en la zona
que se resalta a continuación) el nombre que le queremos dar (vamos a denominarla “cursos”):
Hagamos, paso a paso, lo que nos muestra este ejemplo: dentro del campo de texto
escribamos cursos (en minúsculas), pues ése será el nombre de nuestra nueva base de
datos.
Luego de escribir el nombre, elegiremos el juego de caracteres que almacenaremos
(para textos en español será el utf8_spanish_ci, que corresponde al español tradicional, y
permite que utilicemos la ñ y la ch y ll). Si tuviéramos que crear una base para un cliente co-
reano, japonés, árabe, chino, etc., deberíamos elegir el correspondiente juego de caracteres:
Figura 11-14. Estamos parados dentro de nuestra nueva base de datos llamada “cursos”.
Seguramente, coincidiremos en que ha sido muy fácil. Ya hemos creado nuestra prime-
ra base de datos.
Pero antes de seguir avanzando, comprobemos qué sucedió en el nivel “físico” de nues-
tro disco rígido al crear esta nueva base. Si hemos usado el XAMPP y lo hemos instalado en
la ruta que recomendamos al inicio del libro, entonces podremos entrar con el programa Mi
PC (o cualquier otro explorador de archivos), hasta llegar a C:/servidor/XAMPP/mysql/
data/ y allí encontraremos una carpeta por cada base de datos que hayamos creado; en
este caso, vemos, al lado de las bases que vienen por defecto, nuestra nueva base “cursos”:
Ahora podremos crear una tabla muy fácilmente en la base de datos, simplemente es-
cribiendo el nombre de la tabla que crearemos y la cantidad de campos (columnas) que
deseamos que posea. Esto lo indicaremos en los dos campos de formulario remarcados en
la fgura anterior.
Como primer ejercicio, crearemos una tabla llamada “mensajes” cuyo f n será alma-
cenar el nombre, el correo electrónico y un mensaje que irán dejando los usuarios en un
típico formulario de consultas de nuestro sitio Web.
Es decir, a primera vista parecería que la nueva tabla sólo necesitaría tener tres campos,
uno para cada dato que almacenará (nombre, correo y mensaje); pero en las bases de datos
siempre se utiliza un campo extra, cuyo valor debe ser único en cada registro, siempre
diferente, constituyéndose en un código que permitirá identifcar cada registro de forma in-
equívoca, irrepetible. A este campo extra se lo suele denominar id (ya que cumple la función
de identifcador de cada registro), por lo cual tendremos cuatro campos: id, nombre, email
y mensaje:
enteros, sin decimales, como los que precisa el campo id), VARCHAR
(variable character o caracteres variables, que almacena letras y números,
hasta un máximo de 255 caracteres, como los necesarios para los campos
nombre y email), y TEXT (para textos mayores a 255 caracteres, como los
de nuestro campo mensaje). Así que elegiremos estos tipos de dato en la
columna “Tipo”:
Para eso, no tenemos nada que hacer, ya que por defecto las casillas están
desmarcadas:
Y una vez hecho esto, ¡ya tenemos nuestra primera tabla completamente lista para usar!
A continuación, realizaremos con ella los procesos más necesarios en una base de datos:
agregar, modifcar y borrar datos.
phpMyAdmin o similares), ya que es mucho más sencillo hacerlo de esta forma que mediante
código SQL escrito a mano.
Por el contrario, las tareas de manipulación de datos dentro de la tabla ya creada, las
haremos desde páginas PHP creadas a tal efecto: crearemos un backend o panel de adminis-
tración, que consistirá en una serie de páginas protegidas con usuario y contraseña; páginas
que serán usadas por el dueño o administrador del sitio, donde esta persona autorizada usará
formularios que, una vez completados, agregarán registros a alguna de nuestras tablas, podrá
modifcar el valor de algún campo de determinado registro y, también, podrá borrarlos.
Pero, hasta tanto no aprendamos lo necesario como para hacer esas tareas median-
te código del lenguaje SQL (algo que haremos muy pronto), utilizaremos provisoriamente
el phpMyAdmin y realizaremos “visualmente” las principales tareas de administración del
contenido de una tabla, que son:
1. Agregar nuevos registros.
2. Borrar registros.
3. Modifcar registros.
4. Ver un listado de los registros.
A estas operaciones de manipulación de los datos de una tabla se las conoce como
proceso de ABM (sigla de “Altas”, “Bajas” y “Modifcaciones”). Algunos le agregan a esta sigla
una última letra L o C (la inicial de “Listados” o “Consultas”, respectivamente), denominándolo
ABML o ABMC.
También agregaremos otra tarea: realizar una copia de seguridad (backup) y restaurarla.
Comenzaremos entrando al phpMyAdmin y seleccionando la base cursos:
Luego, una vez que estamos trabajando con la base cursos, veremos en el menú de la
columna izquierda un listado con las tablas que contiene esta base (por ahora hay una sola,
llamada mensajes), y pulsaremos su nombre:
Al hacerlo, aparecerá un formulario desde el que agregaremos uno o dos registros (el
segundo es optativo) y, en este caso, añadiremos uno solo:
Completaremos los datos en la zona derecha del formulario, la que está envuelta en
un recuadro en la imagen anterior. Al campo id no será necesario ingresarle ningún valor, si
bien en la imagen introducimos un 1 , perfectamente podríamos dejarlo vacío, ya que el propio
programa gestor de MySQL le asignará un valor único, sucesivo, automáticamente (al valor
más alto existente del campo id le sumará 1 , y ése será el valor que le pondrá al campo id del
nuevo registro). Esto se debe a que hemos defnido este campo como “A_I” (auto-increment).
Una vez que pulsemos en Continuar, veremos un mensaje de que se logró insertar la
fla, y ya estará habilitado el enlace de la palabra Examinar:
En el extremo izquierdo del registro (antes del valor 1 perteneciente al campo id) ob-
servaremos dos botones, un lápiz y una equis. El primero permite editar (modifcar) ese
registro; la segunda, eliminarlo.
Modifcar un registro
Si queremos modifcar el valor de alguno de los campos de un registro (debido a un cambio
de precio en un producto, por ejemplo), pulsaremos el lápiz correspondiente al registro (ren-
glón) que queremos editar, y aparecerá un formulario con los valores de cada campo de este
registro ya escritos; en ese momento, escribiremos o borraremos lo que queramos, pulsando,
fnalmente, en Continuar para actualizar el registro defnitivamente.
Borrar un registro
Antes de aprender a borrar un registro, vamos a agregar al menos un registro más al que ya
teníamos, para que nuestra tabla no quede vacía luego de eliminar el –hasta ahora– único
registro que posee. Una vez que añadamos algún registro, ya podemos borrar uno, simple-
mente pulsando la equis ubicada en el renglón del registro que queremos eliminar.
Figura 11-33. Pulsamos la equis a la altura del registro que queremos borrar.
y luego marcaremos las opciones SQL, Estructura, Datos y Enviar (Fig. 11-36).
Estas opciones nos abrirán un cuadro de diálogo para que podamos guardar en nuestro
disco rígido un archivo de texto con el nombre de la tabla que estamos exportando, con la
extensión .sql. Por ejemplo, mensajes.sql. Este archivo contiene todas las órdenes escritas
en lenguaje SQL, necesarias para volver a crear en otro servidor una tabla idéntica a la que
hemos exportado.
A este mismo archivo podemos “Importarlo” en otro phpMyAdmin de un hosting, o en
caso de usarlo como copia de seguridad luego de algún borrado de datos, en este mismo
servidor, simplemente yendo al menú Importar, y eligiendo este archivo mensajes.sql, que
hemos dejado a salvo como copia de respaldo. Esto reconstruirá la tabla con todos sus
campos y con idénticos tipos de datos, y cargará dentro de ella todos los datos (registros)
Figura 11-36. Exportaremos código SQL, tanto la estructura de la tabla como sus datos almacenados,
y lo descargaremos.
A continuación, antes de pasar a programar nuestras primeras páginas PHP que lean
datos alojados en una base de datos, vamos a profundizar un poco más en los tipos de da-
tos que podemos defnir en cada campo de nuestras tablas, y analizaremos la conveniencia
de utilizar atributos para controlar con mayor precisión cuál será el contenido de nuestros
campos.
Datos numéricos
La diferencia entre uno y otro tipo de dato es simplemente el rango de valores que puede
contener. Dentro de los datos numéricos, podemos distinguir dos grandes ramas: enteros y
decimales.
Numéricos enteros
Comencemos por conocer las opciones que tenemos para almacenar datos que sean nú-
meros enteros (edades, cantidades, magnitudes sin decimales); poseemos una variedad de
opciones:
Veamos un ejemplo para comprender mejor qué tipo de dato nos conviene elegir para
cada campo. Si necesitamos defnir un campo para almacenar la “edad” de nuestros usua-
rios, sería sufciente con asignar a ese campo un tipo de dato TINYINT, que permite almacenar
como máximo el valor 127 (es decir, por más que tenga tres dígitos, no nos dejará almacenar
un 999, ni siquiera un 128, solo un número hasta el número 127 inclusive). Como la edad
posible de las personas queda incluida en ese rango, es sufciente un TINYINT.
Ahora bien, si queremos defnir el tipo de dato para el campo id (identifcador) de la tabla
de productos de un gran mercado que vende varios miles de artículos diferentes, ya no será
sufciente con un TINYINT, y deberemos conocer con mayor precisión la cantidad de artículos
distintos que comercializa (en la actualidad y la cantidad prevista en un futuro próximo, para
que nuestro sistema de almacenamiento no quede obsoleto rápidamente). Suponiendo que
ese mercado venda 10.000 artículos distintos, el tipo de dato adecuado para el campo id será
SMALLINT, ya que nos permitirá numerar hasta algo más de 32.000 artículos (tal como vimos
en el cuadro anterior).
En el supuesto de que el campo id deba utilizarse para una tabla de clientes de una
empresa telefónica con 5 millones de usuarios, ya no nos serviría un SMALLINT, sino que
deberíamos utilizar un MEDIUMINT.
En el caso de que esa empresa tuviera 200 millones de clientes, deberíamos utilizar un
campo de tipo INT.
Asimismo, si quisiéramos defnir un campo que identifque a cada uno de los seres
humanos que habitamos en el planeta, deberemos recurrir a un campo BIGINT, ya que el tipo
INT sólo permite hasta 2 mil millones de datos diferentes, lo cual no nos alcanzaría.
Vemos, entonces, que hay que considerar siempre cuál será el valor máximo que se
almacenará dentro de un campo, antes de elegir el tipo de dato más adecuado.
Pero no solo los valores máximos deben considerarse, también debemos tener en
cuenta los valores mínimos que pudieran almacenarse. Por ejemplo, para guardar el puntaje
de un juego, que pudiera tomar valores negativos, o el saldo de una cuenta corriente, o una
tabla que incluya valores de temperatura bajo cero, y casos similares. En el cuadro anterior
hemos visto que cada tipo de dato posee valores mínimos negativos simétricos a los valores
positivos máximos que podía almacenar.
Ahora bien: existe la posibilidad de duplicar el límite de valor máximo positivo de cada tipo de
dato, si eliminamos la posibilidad de almacenar valores negativos. Pensemos en los ejemplos
anteriores: la edad no tiene sentido que sea negativa, entonces, si eliminamos la posibilidad
de que ese campo almacene valores negativos, duplicaríamos el límite positivo de almacena-
miento, y el campo de tipo TINYINT que normalmente permitía almacenar valores del -128 al
127, ahora dejará almacenar valores desde el 0 hasta el 255. Esto puede ser útil para almace-
nar precios, cantidades de objetos o magnitudes que no puedan ser negativas, etc.
Observemos en la tabla cómo se duplican los valores máximos sin signo, y luego
aprenderemos cómo confgurar esta posibilidad de quitar el signo desde el phpMyAdmin:
La cantidad de decimales (el segundo número entre los paréntesis) debe estar entre 0 y
24, ya que ése es el rango de precisión simple.
En cambio, en el tipo de dato DOUBLE, al ser de doble precisión, sólo permite que la
cantidad de decimales se defna entre 25 y 53.
Debido a que los cálculos entre campos en MySQL se realizan con doble precisión (la
utilizada por DOUBLE), usar FLOAT, que es de simple precisión, puede traer problemas de
redondeo y pérdida de los decimales restantes.
Por último, DECIMAL es ideal para almacenar valores monetarios, donde se requiera
menor longitud, pero la máxima exactitud (sin redondeos). Este tipo de dato le asigna un
ancho fjo a la cifra que almacenará. El máximo de dígitos totales para este tipo de dato es de
64, de los cuales 30 es el número de decimales máximo permitido. Más que sufciente para
almacenar precios, salarios y monedas.
El formato en el que se defnen en el phpMyAdmin es idéntico para los tres: primero la
longitud total, luego, una coma y, por último, la cantidad de decimales.
Datos alfanuméricos
Para almacenar datos alfanuméricos (cadenas de caracteres) en MySQL poseemos los si-
guientes tipos de dato: CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, TINYTEXT,
BLOB, TEXT, MEDIUMBLOB, MEDIUMTEXT, LONGBLOB, LONGTEXT, ENUM y SET.
Veremos ahora cuáles son sus características y cuáles son las ventajas de usar uno u
otro, según qué datos necesitemos almacenar.
CHAR
Comencemos por el tipo de dato alfanumérico más simple: CHAR (character, o caracter).
Este tipo de dato permite almacenar textos breves, de hasta 255 caracteres de longitud como
máximo. Su característica principal es que consumirá en todos los registros exactamente
el ancho máximo en caracteres que le defnamos, aunque no lo utilicemos. Por ejemplo, si
defniéramos un campo “nombre” de 14 caracteres como CHAR, reservará (y consumirá en
disco) este espacio:
Por lo tanto, no es efciente cuando la longitud del dato que se almacenará en un campo
es desconocida a priori (típicamente, datos ingresados por el usuario en un formulario, como
su nombre, domicilio, etc.).
¿En qué casos usarlo, entonces? Cuando el contenido de ese campo será completado
por nosotros, programadores, al agregarse un registro y, por lo tanto, estamos seguros de
que la longitud siempre será la misma. Pensemos en un formulario con botones de radio
para elegir el “sexo”: independientemente de lo que muestren las etiquetas visibles para el
usuario, podríamos almacenar un solo caracter M o F (masculino o femenino) y, en conse-
cuencia, el ancho del campo CHAR podría ser de un dígito, y sería sufciente. Lo mismo
sucede con códigos que identifquen provincias, países, estados civiles, etc.
VARCHAR
Complementariamente, el tipo de dato VARCHAR (character varying, o caracteres variables)
es útil cuando la longitud del dato es desconocida, cuando depende de la información que
el usuario escribe en campos o áreas de texto de un formulario.
La longitud máxima permitida era de 255 caracteres hasta MySQL 5.0.3, pero desde
esta versión cambió a un máximo de 65.535 caracteres. Este tipo de dato tiene la particula-
ridad de que cada registro puede tener una longitud diferente, que dependerá de su con-
tenido: si en un registro el campo “nombre” (supongamos que hubiera sido defnido con un
ancho máximo de 20 caracteres) contiene solamente el texto: “Pepe”, consumirá solo cinco
caracteres: cuatro para las cuatro letras, y uno más que indicará cuántas letras se utilizaron.
Si luego, en otro registro, se ingresa un nombre de 15 caracteres, consumirá 16 caracteres
(siempre uno más que la longitud del texto, mientras la longitud no supere los 255 caracteres;
si los supera, serán dos los bytes necesarios para indicar la longitud).
Por lo tanto, será más efciente para almacenar registros cuyos valores tengan longi-
tudes variables, ya que si bien “gasta” uno o dos caracteres por registro para declarar la
longitud, esto le permite ahorrar muchos otros caracteres que no serían utilizados. En cambio,
en el caso de datos de longitud siempre constante, sería un desperdicio gastar un caracter
por registro para almacenar la longitud, y por eso convendría utilizar CHAR en esos casos.
BINARY y VARBINARY
Estos dos tipos de datos son idénticos a CHAR y VARCHAR, respectivamente, salvo que
almacenan bytes en lugar de caracteres, una diferencia muy sutil para un nivel básico a inter-
medio de MySQL como el que pretendemos alcanzar con este libro.
TEXT
Antes de la versión 5.0.3 de MySQL, este campo era el utilizado “por excelencia” para des-
cripciones de productos, comentarios, textos de noticias, y cualquier otro texto largo. Pero,
a partir de la posibilidad de utilizar VARCHAR para longitudes de hasta 65.535 caracteres,
es de esperar que se utilice cada vez menos este tipo de campo. La principal desventaja de
TEXT es que no puede indexarse fácilmente (a diferencia de VARCHAR). Muy pronto vere-
mos qué es un índice, y por qué es tan importante que un campo sea fácil de indexar. Tam-
poco se le puede asignar un valor predeterminado a un campo TEXT (un valor por omisión
que se complete automáticamente si no se ha proporcionado un valor al insertar un registro).
Sólo deberíamos utilizarlo para textos realmente muy largos, como los que mencionamos al
comienzo de este párrafo.
BLOB
Es un campo que guarda información en formato binario y se utiliza cuando desde PHP se
almacena en la base de datos el contenido de un archivo binario (típicamente, una imagen o
un archivo comprimido ZIP) leyéndolo byte a byte, y se quiere almacenar todo su contenido
para luego reconstruir el archivo y servirlo al navegador otra vez, sin necesidad de almacenar
la imagen o el ZIP en un disco, sino que sus bytes quedan guardados en un campo de una
tabla de la base de datos. El tamaño máximo que almacena es 65.535 bytes.
De todos modos, y como lo hemos mencionado en este ejemplo, respecto al tipo de
dato para una imagen, usualmente no se guarda “la imagen” (sus bytes, el contenido del ar-
chivo) en la base de datos porque, en un sitio grande, se vuelve muy pesada y lenta la base
de datos; sino que se almacena sólo la URL que lleva hasta la imagen. De esa forma, para
mostrar la imagen simplemente se lee ese campo URL y se completa una etiqueta img con
esa URL, y esto es sufciente para que el navegador muestre la imagen. Entonces, con un
VARCHAR alcanza para almacenar la URL de una imagen. El campo BLOB es para alma-
cenar directamente “la imagen” (o un archivo comprimido, o cualquier otro archivo binario),
no su ruta.
Similares a BLOB, sólo cambia la longitud máxima: en TINYBLOB es de 255 bytes, en ME-
DIUMBLOB es de 16.777.215 bytes, y en LONGBLOB es de cuatro Gb (o lo máximo que
permita manipular el sistema operativo).
ENUM
En este ejemplo, la categoría será excluyente, no podremos elegir más de una, y todo
docente (uno por registro) deberá tener una categoría asignada.
SET
Su nombre signifca “conjunto”. De la misma manera que ENUM, debemos especifcar una
lista, pero de hasta 64 opciones solamente. La carga de esos valores es idéntica a la de
ENUM, una lista de valores entre comillas simples, separados por comas. Pero, a diferencia
de ENUM, sí podemos llegar a dejarlo vacío, sin elegir ninguna opción de las posibles. Y tam-
bién podemos elegir como valor del campo más de uno de los valores de la lista. Por ejem-
plo, damos a elegir una serie de temas (típicamente con casillas de verifcación que permiten
selección múltiple) y luego almacenamos en un solo campo todas las opciones elegidas.
Un detalle importante es que cada valor dentro de la cadena de caracteres no puede
contener comas, ya que es la coma el separador entre un valor y otro.
Una vez defnido ese tipo de dato, podemos cargar valores múltiples para ese campo
dentro de un mismo registro, pulsando Control mientras hacemos clic en cada opción. Eso
signifcará, en este ejemplo de una tabla de alumnos, que ese alumno está cursando ambas
materias seleccionadas.
Si una vez agregado algún registro pulsamos en Examinar para ver el contenido de
la tabla, veremos que este registro, que en un campo contenía un valor múltiple, incluye lo
siguiente:
Con esto damos por fnalizado el grupo de tipos de datos alfanuméricos. Pasemos
ahora al último grupo, el de fechas y horas.
DATE
El tipo de dato DATE nos permite almacenar fechas en el formato: AAAA-MM-DD (los cuatro
primeros dígitos para el año, los dos siguientes para el mes, y los últimos dos para el día).
Atención: en los países de habla hispana estamos acostumbrados a ordenar las fechas en
Día, Mes y Año, pero para MySQL es exactamente al revés. Tengamos en cuenta que esto
nos obligará a realizar algunas maniobras de reordenamiento utilizando funciones de manejo
de caracteres.
Si bien al leer un campo DATE siempre nos entrega los datos separados por guiones, al
momento de insertar un dato nos permite hacerlo tanto en formato de número continuo (por
ejemplo, 20151231), como utilizando cualquier caracter separador (2015-12-31 o cualquier
otro caracter que separe los tres grupos).
El rango de fechas que permite manejar va desde el 1000-01-01 hasta el 9999-12-31.
Es decir, que no nos será útil si trabajamos con una línea de tiempo que se remonte antes
del año 1000 (¿alguna aplicación relacionada con la historia?), pero sí nos resultará útil para
datos de un pasado cercano y un futuro muy largo por delante, ya que llega casi hasta el año
10.000.
DATETIME
Un campo defnido como DATETIME nos permitirá almacenar información acerca de un ins-
tante de tiempo, pero no sólo la fecha sino también su horario, en el formato: AAAA-MM-DD
HH:MM:SS, siendo la parte de la fecha de un rango similar al del tipo DATE (desde el 1000-
01-01 00:00:00 al 9999-12-31 23:59:59), y la parte del horario, de 00:00:00 a 23:59:59.
TIME
Este tipo de campo permite almacenar horas, minutos y segundos, en el formato HH:MM:SS,
y su rango permitido va desde -839:59:59 hasta 839:59:59 (unos 35 días hacia atrás y hacia
adelante de la fecha actual). Esto lo hace ideal para calcular tiempos transcurridos entre dos
momentos cercanos.
TIMESTAMP
Un campo que tenga defnido el tipo de dato TIMESTAMP sirve para almacenar una fecha y un
horario, de manera similar a DATETIME, pero su formato y rango de valores serán diferentes.
Figura 11-46. Campos cuyo valor se actualizará automáticamente al insertar o modifcar un registro.
YEAR
En caso de defnir un campo como YEAR, podremos almacenar un año, tanto utilizando dos
como cuatro dígitos. En caso de hacerlo en dos dígitos, el rango posible se extenderá desde
70 hasta 69 (del 70 hasta el 99 se entenderá que corresponden al rango de años entre 1970
y 1999, y del 00 al 69 se entenderá que se referen a los años 2000 a 2069); en caso de
proporcionar los cuatro dígitos, el rango posible se ampliará, yendo desde 1901 hasta 2155.
Una posibilidad extra, ajena a MySQL pero relativa a las fechas y horarios, es generar
un valor de timestamp con la función time de PHP (repito, no estamos hablando de MySQL,
no nos confundamos a causa de tantos nombres similares). A ese valor, lo podemos almace-
nar en un campo INT de 10 dígitos. De esa forma, será muy simple ordenar los valores de
ese campo (supongamos que es la fecha de una noticia) y luego podremos mostrar la fecha
transformando ese valor de timestamp en algo legible mediante funciones de manejo de fecha
propias de PHP.
2. Podemos defnir que el valor por omisión sea NULL, es decir, que si no se propor-
ciona un valor, quede el valor NULL como valor de ese campo.
3. Y, por último, podemos defnir para un campo de tipo TIMESTAMP que se inserte
como valor por defecto el valor actual de TIMESTAMP (Current_Timestamp), algo
que ya hemos visto en detalle al referirnos a este tipo de dato.
En los dos últimos casos, debemos dejar vacío el cuadro de texto inferior.
Ordenamiento binario
Defnir un campo de texto CHAR o VARCHAR como BINARY (binario) sólo afecta en el orde-
namiento de los datos: en vez de ser indiferentes a mayúsculas y minúsculas, un campo BI-
NARY se ordenará teniendo en cuenta esta diferencia, por lo cual, a igualdad de letra, primero
aparecerán los datos que contengan esa letra en mayúsculas.
Se defne desde el phpMyAdmin eligiendo BINARY en el menú Atributos:
Índices
El objetivo de crear un índice es mantener ordenados los registros por aquellos campos que
sean frecuentemente utilizados en búsquedas, para así agilizar los tiempos de respuesta. Un
índice no es más que una tabla “paralela”, que guarda los mismos datos que la tabla original,
pero en vez de estar ordenados por orden de inserción o por la clave primaria de la tabla, en
el índice se ordenan por el campo que elegimos indexar.
Por ejemplo, si hubiera un buscador por título de noticia, en la tabla de noticias le
asignaríamos un índice al campo “título”, y las noticias estarían ordenadas de la “a” a la “z”
por su título. La búsqueda se realizará primero en el índice, encontrando rápidamente el título
buscado, ya que están todos ordenados y, como resultado, el índice le devolverá al programa
MySQL el identifcador (id) del registro en la tabla original, para que MySQL vaya directamente
a buscar ese registro con el resto de los datos, sin perder tiempo. Todo esto, por supuesto,
de manera completamente invisible para nosotros.
Para indicar que queremos crear un índice ordenado por un campo determinado, al
campo que se indexará debemos especifcarle, dentro del atributo Indice, del menú de selec-
ción que aparece a su derecha, la opción Index:
Como podemos apreciar, dentro del menú Indice aparecen otras opciones: Primary,
Unique y Fulltext. Veamos en qué consiste cada una de estas variantes.
Siempre, en toda tabla, uno de los campos (por convención, el primero, y también por
convención, usualmente llamado id –por “identifcador”–), debe ser defnido como clave
primaria o Primary Key. Esto impedirá que se le inserten valores repetidos y que se deje
nulo su valor.
Habitualmente, se especifca que el campo elegido para clave primaria sea numéri-
co, de tipo entero (en cualquiera de sus variantes, según la cantidad de elementos que se
identifcarán), y se le asigna otro atributo típico, que es Auto_Increment, es decir, que no
nos preocupamos por darle valor a ese campo: al agregar un registro, MySQL se ocupa de
incrementar en uno el valor de la clave primaria del último registro agregado, y se lo asigna al
nuevo registro. Este campo no suele tener ninguna relación con el contenido de la tabla, su
objetivo es simplemente identifcar cada registro de forma única, irrepetible.
Podemos defnir un solo campo como clave primaria, o dos o más campos combina-
dos. En caso de haber defnido dos o más campos para que juntos formen el valor único de
una clave primaria, diremos que se trata de una clave primaria “combinada” o “compuesta”.
UNIQUE
Si especifcamos que el valor de un campo sea Unique, estaremos obligando a que su valor
no pueda repetirse en más de un registro, pero no por eso el campo se considerará clave
primaria de cada registro. Esto es útil para un campo que guarde, por ejemplo, números de
documentos de identidad, la casilla de correo electrónico usada para identifcar el acceso
de un usuario, un nombre de usuario, o cualquier otro dato que no debamos permitir que se
repita. Los intentos por agregar un nuevo registro que contenga un valor ya existente en ese
campo, serán rechazados.
FULLTEXT
Si en un campo de tipo TEXT creamos un índice de tipo FULLTEXT, MySQL examinará el con-
tenido de este campo palabra por palabra, almacenando cada palabra en una celda de una
matriz, permitiendo hacer búsquedas de palabras contenidas dentro del campo, y no ya una
simple búsqueda de coincidencia total del valor del campo, que son mucho más rápidas pero
no sirven en el caso de búsquedas dentro de, por ejemplo, el cuerpo de una noticia, donde el
usuario desea encontrar noticias que mencionan determinada palabra.
Se ignoran las palabras de menos de cuatro caracteres y palabras comunes como ar-
tículos, etc. que se consideran irrelevantes para una búsqueda, así como también se ignoran
diferencias entre mayúsculas y minúsculas. Además, si la palabra buscada se encuentra en
más del 50% de los registros, no devolverá resultados, ya que se la considera irrelevante por
“exceso” de aparición (deberemos refnar la búsqueda en este caso).
Con esto, damos por terminada esta revisión bastante exhaustiva. Ya hemos aprendido
a crear una base de datos y una tabla, defniendo con total precisión sus campos valiéndonos
de tipos de datos y atributos, por lo tanto, estamos en condiciones de comenzar a programar
todo lo necesario para que nuestras páginas PHP se conecten con una base de datos y pue-
dan enviarle o le soliciten datos. Justamente, éste será el tema del próximo capítulo.
Vamos a aprender estos pasos con un ejemplo concreto: construiremos una página que
muestre el contenido de la tabla “mensajes” creada anteriormente.
Probar la conexión
El programa intérprete de PHP –que procesa nuestro código PHP– le debe demostrar al pro-
grama gestor de MySQL que tiene autorización para solicitarle datos.
Para intentar establecer una conexión entre estos dos programas, utilizaremos la fun-
ción mysql_connect, que requiere que completemos tres parámetros: host, usuario y cla-
ve (de MySQL, por supuesto: el usuario “root” al que le habíamos creado la contraseña
“clave”), en ese orden, en consecuencia la estructura básica de esta función será:
<?php
mysql_connect("host","usuario","clave");
?>
<?php
mysql_connect("localhost","root","clave");
?>
En el raro caso de una intranet con distintas máquinas para el intérprete de PHP y el
programa gestor de MySQL, quedará algo como lo que se expresa a continuación (obviamen-
te los datos no son reales):
<?php
mysql_connect(123.456.10.1,"usuario","password");
?>
Al ser mysql_connect una función que sólo puede devolver “verdadero” o “falso”
(booleana), es posible envolverla dentro de un condicional que evaluará si MySQL nos autori-
za que le enviemos consultas, o no:
<?php
if ( mysql_connect("localhost","root","clave") ){
} else {
}
?>
Con esto ya tenemos listo el primer paso. Nuestro programa intérprete de PHP ya tiene
autorización para realizar consultas al programa gestor de MySQL. Ahora, es momento de
crear la consulta que ejecutaremos.
Esta orden seleccionará los campos (columnas) nombre y email a través de todos los
registros de nuestra tabla denominada mensajes. Es decir, devolverá todos los registros
(flas) de la tabla, pero “cortados” verticalmente, extrayendo sólo las dos columnas solicitadas
(nombre y email), en consecuencia, nos llegaría lo siguiente (probemos insertar varios registros
antes de hacer esto):
Pepe pepe@pepe.com
Carlos carlos@garcia.com
Alberto alberto@perez.com
Si, en cambio, quisiéramos traer “todos los campos” de la tabla (tarea muy frecuente
y, que en caso de tener muchos campos la tabla, podría resultar bastante tedioso completar
sus nombres uno por uno) podemos utilizar un carácter que cumple las funciones de comodín
para simbolizar “todos los campos de la tabla”. Este caracter es el asterisco, con el cual la
orden quedaría:
Esta orden traería todas las columnas (campos) de la tabla mensajes (y, desde ya, todos
los registros también):
Nota al margen: aquellos curiosos que deseen “jugar” y practicar consultas SQL desde
el phpMyAdmin, pueden hacerlo pulsando en la solapa SQL y, a continuación, podrán
escribir sus órdenes en lenguaje SQL dentro del área de texto y pulsar Continuar para
ver el resultado de su ejecución.
Resumiendo, para fnalizar este segundo paso, podemos almacenar la orden SQL en
una variable (hasta el momento en que la necesitemos):
<?php
$consulta = "SELECT * FROM mensajes";
?>
Ahora que tenemos preparada nuestra orden SQL, es momento de pasar al tercer
paso y hacer que el intérprete de PHP se la envíe al gestor de MySQL, obteniendo alguna
respuesta.
<?php
mysql_select_db("cursos");
?>
<?php
mysql_query($consulta);
?>
Por ejemplo:
<?php
$datos = mysql_query($consulta);
?>
De esta manera, culminamos el tercer paso y estamos listos para el cuarto y último
paso.
<?php
$fla = mysql_fetch_array($datos);
?>
En este momento, $fla es una matriz (o array, por eso lo de ...fetch_array) que contie-
ne la primera f l a completa de la tabla, con los valores de sus cuatro campos ubicados en
cuatro celdas de la matriz $fla. Los índices alfanuméricos de esta matriz $fla, que contiene un
registro de la tabla, son los nombres que tenían los campos en la tabla.
En este momento, $fla[“id”] contiene un “1”, $fla[“nombre”] contiene “Pepe”, $fla[“email”]
contiene “pepe@pepe.com” y $fla[“mensaje”] contiene “Bla, bla, bla...”.
Pero, ¿qué pasará con el resto de flas que no hemos leído? La función mysql_fetch_
array sólo lee una fla cada vez que se ejecuta. Para poder leer no solo la primera, sino tam-
bién el resto de las flas, deberíamos realizar un bucle, que ejecute esta lectura y asignación
de una fla de datos por vez, repetitivamente, mientras todavía quede dentro de $datos
alguna fla que asignar (será un bucle de tipo while, ya que no sabemos de antemano cuántas
flas nos devolverá la consulta).
En cuanto se almacene una fla en la matriz, la deberemos mostrar inmediatamente (es-
cribir en pantalla con un print o echo), ya que una vuelta después del bucle, el contenido de
$fla será borrado para permitir almacenar los valores de la siguiente f l a de la tabla.
La condición del bucle será “mientras podamos descomprimir con mysql_fetch_array
una nueva fla del paquete de datos, y almacenarla en una matriz”... Pensemos esto deteni-
damente, y veamos cómo sería esa parte:
<?php
while ( $fla = mysql_fetch_array($datos) ){
echo "<p>";
echo $fla["id"];
echo " - " ; // un separador
echo $fla["nombre"];
echo " - " ; // un separador
echo $fla["email"];
echo " - " ; // un separador
echo $fla["mensaje"];
echo "</p>";
}
?>
Para terminar, veamos un ejemplo completo, pasado en limpio, de los cuatro pasos
juntos:
<?php
// 1 ) Conexión
if ($conexion = mysql_connect("localhost","root","clave")){
$datos = mysql_query($consulta);
echo "<p>";
echo $fla["id"];
echo " - " ; // un separador
echo $fla["nombre"];
echo " - " ; // un separador
echo $fla["email"];
echo " - " ; // un separador
echo $fla["mensaje"];
echo "</p>";
}
} else {
echo "<p>MySQL no conoce ese usuario y password</
p>";
}
?>
Ahora sí que estamos preparados para mostrar los datos almacenados en nuestras
tablas. Vamos a volver a hacer esto miles de veces, cambiando “productos” por “mensajes”,
“empleados”, “comentarios”, o lo que sea que haya que mostrar en una página de nuestro
sitio.
Desde ya que la forma de mostrar estos datos dentro del código HTML irá variando: en
algunos casos, precisaremos mostrar un texto (párrafos como los del ejemplo anterior); en
otros, necesitaremos generar etiquetas option dentro de un elemento select; otras veces,
flas de una tabla; o botones de tipo radio, o casillas de verifcación. Lo ideal es que nos vaya-
mos creando una serie de funciones, que reciban como parámetros el nombre de la tabla y
los campos que se seleccionarán, más algún dato específco (label, name, elemento a mostrar
seleccionado, etc,) y que devuelvan el bloque HTML completo cargado con los datos de la
tabla. En este mismo capítulo veremos algunos ejemplos útiles, pero antes vamos a profundi-
zar un poco más en la estructura de la orden SELECT del lenguaje SQL, para que podamos
aprovechar toda su potencia.
Podemos escribir esta orden dentro de la ventana de ejecución de código SQL del
phpMyAdmin, y la tabla será creada idéntica a la original:
Una vez creada la tabla, vamos a cargar varios registros con diferentes valores en
los distintos campos, para poder utilizarlos en las órdenes de selección condicional. Reco-
mendamos cargar los siguientes datos, ya que fueron elegidos especialmente para mostrar
resultados signifcativos en las consultas que realizaremos a continuación:
Figura 12-2. Datos de ejemplo, cargados con la intención de usarlos en selecciones condicionales.
El condicional WHERE
A nuestras órdenes SELECT será muy común que les agreguemos condiciones, para que
nos devuelvan un conjunto menor de resultados: solo aquellos registros que cumplan con la
condición. La condición tomará en cuenta el valor de alguno de los campos. Por ejemplo,
imaginemos que necesitamos una lista de los empleados de la tabla anterior, pero no todos,
sino solo aquellos cuya especialidad sea “Matemáticas”.
La sintaxis de la expresión condicional WHERE es similar a la de un if: se trata de una
afrmación en la forma de una comparación, cuyos elementos serán un campo de la tabla,
un operador de comparación y un valor contra el que se compara:
...WHERE especialidad='Matemáticas'
Y completando la orden SELECT con esta condición, tendríamos una orden completa:
Los operadores de los que disponemos dentro de un WHERE son muy similares a los que
usamos en los condicionales de PHP, salvo el último, denominado LIKE, que enseguida
analizaremos:
Cuadro 12-1. Operadores de comparación de SQL.
Operador Signifca
= Igual
<> Distinto de
También podemos unir varias condiciones mediante los operadores lógicos AND y OR.
Veamos un ejemplo de OR (nos devolverá tanto los empleados que en su campo “pais”
fgure el valor “España” como los que sean de “Argentina”):
En cambio, al combinar condiciones con AND, los resultados serán más específcos:
sólo aquellos registros que cumplan con todas las condiciones unidas mediante AND:
También, podemos buscar coincidencias con varios valores posibles para un campo, y
no con uno solo, usando IN:
De esta manera, proporcionamos, en un solo paso, una lista de valores para el campo
“pais”, que, en este ejemplo, nos devolverá los registros de empleados cuyo país sea México,
Argentina o Perú.
Eso nos devolverá tres registros, a partir del primero, pero no del primero físicamente
en la tabla, sino el primero de los resultados que hubiera devuelto la consulta ordenada por
apellido, es decir, el de apellido más cercano a la A.
Si en un paginador tuviéramos que realizar otra consulta para traer los tres siguientes,
lo único que cambiará es el valor de inicio de LIMIT:
Funciones estadísticas
Muchas veces, no necesitaremos que una consulta nos devuelva “los datos” que están alma-
cenados en la tabla, sino alguna información estadística “acerca de” esos datos. Por ejemplo,
cuántos registros logró seleccionar una consulta, cuál es el valor mínimo o máximo de un
campo, cuál es la sumatoria de los valores de ese campo a lo largo de todos los registros,
o cuál es el valor promedio:
Supongamos que creamos un archivo llamado datos.php con ese objetivo. Su conte-
nido será el siguiente:
<?php
$host = "localhost";
$usuario = "root";
$clave = "clave";
$base = "cursos";
?>
Luego haremos un include de ese archivo dentro de cada página donde vayamos a
conectarnos con la base de datos, y usaremos esas variables en las funciones.
Por ejemplo:
<?php
// Incluimos esos datos:
include("datos.php");
// etc.
?>
Crearemos entonces una función booleana (que devuelva true o false, así podemos
evaluarla dentro de un condicional al momento de ejecutarla):
<?php
function conectarBase($host,$usuario,$clave,$base){
if (!$enlace = mysql_connect($host,$usuario,$clave)){
return false;
} elseif (!mysql_select_db($base)){
return false;
} else {
return true;
}
}
?>
A esta función, tal como vimos en la fgura anterior, la crearemos dentro de un archivo
externo llamado funciones.php, al que también lo incluiremos dentro de las páginas median-
te una orden include:
include("datos.php");
include("funciones.php");
Sin embargo, en esta función todavía existe un problema, que podemos comprobar
fácilmente si modifcamos intencionalmente alguno de los datos de conexión (probemos cam-
biando el host, usuario o clave, por uno que no sea el correcto), y es que, si llega a fallar el
intento de conexión, aparecerá en la pantalla un mensaje de error en inglés.
Podemos ocultar fácilmente ese mensaje de error si anteponemos a la función de PHP
que produce el error (mysql_connect, en este caso) el operador de control de errores de PHP,
que es una simple arroba:
<?php
function conectarBase($host,$usuario,$clave,$base){
if (!$enlace = @mysql_connect($host,$usuario,$clave)){
// notemos la arroba antepuesta a la función que de-
volvía error
return false;
} elseif (!mysql_select_db($base)){
return false;
} else {
return true;
}
}
?>
Este operador de control de errores (la arroba) lo podemos anteponer a cualquier expre-
sión que devuelva datos (como, por ejemplo, una llamada a una función, una orden include,
una variable o una constante), y de esta forma evitamos que se muestre el mensaje de error
de PHP en caso de fallo.
Volviendo a la función que acabamos de crear, la utilizaríamos desde nuestras páginas
dentro de un condicional:
<?php
// Incluimos los datos de conexión y las funciones:
include("datos.php");
include("funciones.php");
if ( conectarBase($host,$usuario,$clave,$base) ){
} else {
}
?>
2) Ahora, es momento de crear una función que nos permita realizar una consulta a la
base de datos, obteniendo un paquete de datos como respuesta (o false en caso de fallo).
Esa función podría ser así:
<?php
function consultar($consulta){
if (!$datos = mysql_query($consulta) or mysql_num_
rows($datos)<1){
} else {
}
}
?>
<?php
// Incluimos los datos de conexión y las funciones:
include("datos.php");
include("funciones.php");
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( $paquete = consultar($consulta) ){
} else {
} else {
}
?>
3) Por último, sólo nos falta crear distintas funciones que se ocupen de mostrar el “pa-
quete” de datos recibido, con la diferencia de que cada una se especializará en mostrar los
datos dentro de distintas etiquetas HTML: veremos cómo mostrar datos dentro de un menú
de selección, una tabla, botones de radio y casillas de verifcación.
<?php
function generaMenuSeleccion($datos,$name,$label){
$codigo = '<label>'.$label.'</label>'."\n";
$codigo = $codigo.'<select name="'.$name.'">'."\n";
while($fla = mysql_fetch_array($datos)){
$codigo = $codigo.'<option
value="'.$fla["id"].'">'.utf8_encode($fla["pais"]).'</
option>'."\n";
$codigo = $codigo."</select>\n";
En la página donde vayamos a llamar a esa función, recibiremos en una variable el có-
digo que fue acumulando la función internamente en su variable local $codigo, y allí quedará
(en la variable $codigoMenu, en este ejemplo) hasta que decidamos usarlo. En este caso,
inmediatamente lo mostramos con un echo.
Recordemos que ya contábamos con un $paquete de datos, que es lo que pasaremos
como parámetro a la función:
$codigoMenu = generaMenuSeleccion($paquete,$name,$label);
echo $codigoMenu;
Estas dos líneas irían colocadas en la parte del código anterior donde dejamos el co-
mentario que decía “// Aquí llamaremos a una función que muestre esos datos”.
Lo cual producirá, en el caso de nuestra tabla de empleados, el siguiente código HTML:
<label>Empleados</label>
<select name="empleados">
<option value="1">Pedro</option>
<option value="2">José</option>
<option value="3">Guillermo</option>
<option value="4">Alberto</option>
<option value="5">Luis</option>
<option value="6">Claudio</option>
<option value="7">Mario</option>
<option value="8">Alan</option>
</select>
Vemos los valores de label y del name (proporcionados como parámetros al momento
de llamar a la función), y luego los valores envueltos entre la apertura y cierre de cada etiqueta
option (obtenidos gracias a la consulta a la base de datos).
Esta misma lógica, podemos aplicarla para envolver los datos obtenidos en cualquier
otra etiqueta HTML. Veremos, a continuación, algunos ejemplos más.
<?php
function tabular($datos){
$codigo .= '<tr>';
// Cerramos un "tr":
Podemos usarla igual que la función anterior, a partir de un paquete de datos ya obteni-
do y asignando el código que fabrica a una variable, que luego mostramos con echo.
<?php
function crearRadios($datos,$leyenda,$name){
// Un label:
$codigo .= '<label>'.utf8_encode($fla["nombre"]);
// Un input:
$codigo = $codigo.'<input type="radio"
name="'.$name.'" id="dato'.$fla["id"].'" />'."\n";
// Cerramos el label:
$codigo .= '</feldset>'."\n";
return $codigo;
}
?>
Podríamos llamarla dentro del mismo archivo que realizaba la conexión y ejecutaba una
consulta obteniendo un paquete de datos, de la siguiente manera:
echo $radios;
Por último, las casillas de verifcación: como sabemos, en ellas cada name debe ser
diferente, por lo que lo formaremos uniendo a una parte escrita de manera fja el identifcador
de cada registro, como hicimos con los id en el ejemplo anterior, de los botones de radio:
<?php
function crearCasillas($datos,$leyenda){
// Un label:
$codigo .= '<label>'.utf8_encode($fla["nombre"]);
// Un input:
$codigo = $codigo.'<input type="checkbox"
name="dato'.$fla["id"].'" id="dato'.$fla["id"].'"
/>'."\n";
// Cerramos el label:
Será muy útil seguir creando tantas funciones como consideremos necesario, para
mostrar datos de distintas formas dentro de etiquetas HTML, ya que las necesitaremos con-
tinuamente en nuestro trabajo con bases de datos.
El objetivo de la creación de todas estas funciones es organizar nuestro código para
que no quede suelto (que lo vuelve muy difícil de reutilizar). Podemos notar cómo la cantidad
de código suelto dentro de nuestras páginas es cada vez menor, consistiendo en apenas
un par de includes (del archivo de “datos” y del de “funciones”), algunos condicionales que
validan datos y deciden cuál función ejecutar, y nada más.
Esta forma de programación modularizada o estructurada en funciones, facilita muchí-
simo el mantenimiento, y hace que futuros cambios (siempre imprevisibles) no nos obliguen
a modifcar las “páginas” una por una, sino sólo el archivo donde esté la declaración de
nuestras funciones.
Con esto, ya dominamos sufcientes técnicas para enviar datos desde la base hacia
nuestras páginas. Llega el momento de agregar interactividad y hacer el recorrido inverso,
llevando datos desde la pantalla del usuario hacia nuestra base de datos, tema del que nos
ocuparemos en el siguiente capítulo.
utilicen páginas HTML para escribir algo y enviarlo hacia el servidor desde el front-
end (las páginas “públicas” de nuestro sitio).
Sea quien fuere el tipo de usuario que agregará datos a nuestra base, lo hará utilizando
una misma técnica: un formulario HTML para escribir los datos del lado del cliente (nave-
gador) y, en la página de destino de ese formulario, un código PHP que, al estar ubicado
del lado del servidor, podrá insertar los datos en la base y luego devolver alguna respuesta al
navegador.
Entonces, estamos hablando de un proceso que tiene dos etapas o “momentos”:
• el momento inicial donde el usuario completa el formulario, del lado del cliente;
• y, el segundo, cuando una página PHP recibe en el servidor las variables que el
usuario completó y las utiliza para ejecutar una consulta SQL que inserta los
datos en la base.
Típicamente, este proceso se dividirá en dos páginas distintas: un archivo HTML para
el formulario y una página PHP para el código que se ejecutará en el servidor, insertará el dato
en la base y mostrará un mensaje de éxito o error.
Figura 13-2. Dos páginas: un formulario envía datos y, otra, los recibe y los inserta en la base.
En la segunda página (agregar.php), para insertar los registros en la base, los pasos
necesarios serán:
1. Que el programa intérprete de PHP se identifque ante el programa gestor de
MySQL y seleccione una base (ya hemos creado una función que hacía esto en
el capítulo anterior, así que podremos reutilizarla).
2. Prepararemos en una variable la orden del lenguaje SQL necesaria para insertar
datos en la base.
3. Ejecutaremos esa orden SQL (no será necesario crear una función específca
para insertar datos, ya que esta consulta no trae datos, sino que los envía hacia
la base, por lo cual no es necesario generar ni recorrer luego ningún “paquete de
datos”). Ejecutaremos la orden con mysql_query directamente, y será fundamental
evaluar si devolvió verdadero o no la ejecución de esa consulta y, en función de
ello, mostraremos un mensaje de éxito (si el dato fue insertado) o de error.
Pasemos a la acción:
Creando el formulario
Como primera medida, crearemos un formulario que nos dejará escribir los datos que que-
remos agregar a la tabla de “mensajes”. Este formulario tendrá dos campos de texto, para el
nombre y el email, respectivamente, y un área de texto para el mensaje (el id no lo insertará
el usuario, ya que es un campo auto-increment).
A este formulario lo llamaremos formulario.html, y su código podría ser algo así:
Además de prestar atención a los name (ya que serán los nombres de las variables que
podremos leer en la siguiente página desde una celda de la matriz $_POST), lo más impor-
tante aquí es que el atributo action del formulario está apuntando hacia una segunda página,
llamada agregar.php; que será la que codifcaremos a continuación.
Conexión a MySQL
En la segunda página (es decir, aquella página hacia la cual apuntaba el action del formulario
anterior y que decidimos denominar agregar.php), luego de validar si se recibieron las varia-
bles, el intérprete de PHP intentará conectarse al programa MySQL, y tratará de seleccio-
nar una base.
Para estas tareas, ya habíamos creado una función en el capítulo anterior, así que va-
mos a reutilizarla:
<?php
// Incluimos los datos de conexión y las funciones:
include("datos.php");
include("funciones.php");
if ( conectarBase($host,$usuario,$clave,$base) ){
} else {
}
?>
Esto podría traducirse como “Insertar en la tabla indicada, en los campos enumerados,
los valores siguientes”.
Veamos un ejemplo para entenderlo mejor:
Observemos que los valores (enumerados entre paréntesis luego de la palabra VA-
LUES) siempre van envueltos entre comillas simples, y que existe una correlación de orden,
ya que se insertará, en el primer campo de la lista (el campo id, en este caso), el primero de los
value (el 0); en el segundo (nombre), el segundo value (Hernán), y así sucesivamente.
Notemos también que hemos proporcionado un cero como valor para el campo id,
ya que será generado automáticamente (lo hemos defnido como auto-increment). De esta
manera, nos despreocuparemos y, para todos los registros que vayamos a insertar, siempre
proporcionaremos un cero como valor del id, y será MySQL quien se ocupe de asignarle el
valor correspondiente (por supuesto, todo esto gracias a que hemos defnido al campo id
como auto-increment).
A esta orden INSERT, del lenguaje SQL, la dejaremos escrita dentro de una variable,
para que la podamos pasar como parámetro a una función que se encargue de ejecutarla.
Pero no vamos a escribir allí los datos “a mano”, como en el ejemplo anterior, sino que
deberemos modifcar esta orden para que realmente reciba los datos enviados desde el for-
mulario de la primera página, por lo cual quedará algo como lo que sigue:
<?php
// Validamos que hayan llegado estas variables, y que no estén
vacías:
if ( isset($_POST["nombre"],$_POST["email"],$_POST["mensaje"])
and $_POST["nombre"]!="" and $_POST["email"]!="" and ]
$_POST["mensaje"]!="" ){
} else {
Lo más importante aquí es que verifcamos la presencia de las variables, y las dejamos
preparadas, listas para usar dentro de $consulta.
Es muy útil, llegados a este punto previo a la ejecución de la consulta, que probemos
qué contiene la variable $consulta haciendo un echo de ella. Podemos completar algunos
datos de prueba en el formulario, enviarlo, y ver qué muestra el echo; a eso que muestre,
podemos copiarlo y pegarlo dentro de la ventana SQL del phpMyAdmin para, de esta manera,
confrmar si la sintaxis de la orden fue la correcta.
Recordemos que es necesario que incluyamos este bloque de código dentro del bloque
anterior que realizaba la conexión a la base, en la parte exacta en la que habíamos dejado
preparado un comentario que decía: “// Aquí irá el resto”.
Ejecutar la consulta
Ahora que hemos verifcado que la sintaxis de la consulta es la correcta, ya podemos hacer
que PHP la ejecute realmente, mediante la utilización de la conocida función mysql_query,
Observemos que el siguiente código debe ser intercalado en el punto del código anterior
en el que dejamos un comentario que decía: “// Aquí ejecutaremos esa orden”.
if ( mysql_query($consulta) ){
} else {
Con esto, el proceso completo de agregar registros a una tabla desde un formulario ya
funciona pero, antes de usarlo en nuestros sitios, analizaremos un típico problema de seguri-
dad (y veremos cómo solucionarlo) de este proceso de agregar a la base información que fue
ingresada por algún usuario.
A esta técnica se la conoce como SQL injection (inyección SQL), y consiste en utilizar un
campo de un formulario para “complementar” una consulta SQL (SELECT, INSERT, DELETE o
UPDATE). Por supuesto, los atacantes conocen el lenguaje SQL muy bien.
Veamos un ejemplo de esta técnica en funcionamiento, para que podamos comprobar
el riesgo real de no “limpiar” los datos escritos por los usuarios.
Vamos a crear una tabla llamada “usuarios”, que tendrá solo tres campos: id (TINYINT),
usuario y clave (ambos VARCHAR). Cargaremos un solo registro, un supuesto usuario “pepe”
con la clave “clave”.
Una vez creada esta sencilla tabla e insertado ese registro de prueba, crearemos un
archivo “formulario.html” en el que se pueda ingresar un usuario y clave para acceder a un
supuesto contenido secreto:
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
// Nos conectamos:
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( $paquete = consultar($consulta) ){
} else {
} else {
} else {
Notemos que se modifca radicalmente la consulta; ya no importa qué haya sido ingre-
sado en el campo usuario (puede ser cualquier cosa), ni importa que se haya dejado vacía la
clave, ya que con su primera comilla simple, ha cerrado la comilla que quedaba abierta para
la clave, pero luego ha agregado: OR ''='' que es una afrmación verdadera, también podría
haber puesto: OR 1=1, o cualquier otra tautología que provoque que la expresión completa
sea evaluada como verdadera. El punto de que sea evaluada como verdadera, es que, re-
cordemos... está siendo ejecutada dentro de un condicional, que es la única manera de saber
si “existían” ese usuario y esa clave en la tabla de usuarios. Conclusión: este condicional dará
siempre verdadero para ese usuario, que podrá entrar libremente a nuestra zona “secreta”,
simplemente inyectando el mencionado código en nuestro formulario de acceso.
¿Cómo podemos evitarlo? Muy fácilmente: contamos con una función denominada
mysql_real_escape_string que nos permite sanear los datos ingresados por el usuario, es
decir, cambiar su valor por otro que resulte inofensivo para las consultas SQL que se enviarán
hacia la base de datos.
Sólo debemos aplicarla a las variables recibidas, y desaparece el riesgo de inyección SQL:
$usuario = mysql_real_escape_string($_POST["usuario"]);
$password = mysql_real_escape_string($_POST["clave"]);
Si por curiosidad completamos nuevamente el formulario con ' OR ''=' y luego hacemos
un echo de $password para ver qué contiene, veremos que las comillas fueron desactivadas
(“escapadas” con una barra invertida delante):
\ ' OR \'\'=\'
Esta operación lo vuelve completamente inofensivo debido a que ya no respeta la sin-
taxis del lenguaje SQL y, por lo tanto, el usuario que intentó esta inyección SQL ya no podrá
acceder a nuestro contenido secreto.
Ahora que ya podemos insertar datos en la base desde nuestras páginas PHP con
total seguridad, aprenderemos a eliminar un registro de la base mediante formularios (tarea
típica de un panel de administración o back-end, desde el cual, por ejemplo, podríamos
eliminar un mensaje publicado en un foro que sea ofensivo o que realice SPAM, eliminar un
producto agotado, que ya no esté en venta en un catálogo, etc.).
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
if ( $paquete = consultar($consulta) ){
$codigoTabla = tabular($paquete);
echo $codigoTabla;
} else {
} else {
}
?>
La parte clave del bucle de nuestra función llamada tabular, donde se armaba el código
HTML de cada renglón o tr del listado, era la siguiente:
$codigo .= '<tr>';
$codigo .= '<td>'.utf8_encode($fla["nombre"]).'</
td>';
$codigo .= '<td>'.utf8_encode($fla["apellido"]).'</
td>';
$codigo .= '<td>'.utf8_encode($fla["edad"]).'</td>';
// Cerramos un "tr":
$codigo .= '</tr>';
}
\i Alan Flores 25
, Perú Sistemas
Para agregar a este listado tanto la operación de borrar como la de modifcar un regis-
tro, agregaremos un par de nuevas columnas td a cada fla, para que incluyan cada una un
enlace que muestre las palabras BORRAR y MODIFICAR, respectivamente.
Para ello, agregaremos al bucle anterior dos nuevos td al fnal de los demás, de esta
manera:
$codigo .= '<td>BORRAR</td>';
$codigo .= '<td>MODIFICAR</td>';
Pero ahora necesitamos que, al pulsar una de estas palabras, cada una de ellas “envíe”
hacia el servidor en un enlace (que aún no hemos hecho) una variable con el código del re-
gistro que deseamos borrar o modifcar. Ésta es la forma para que la página de destino sepa
“a cuál registro” se está queriendo eliminar o modifcar.
Comencemos convirtiendo la palabra BORRAR en un simple enlace HTML, que apunte
hacia una página que denominaremos borrar.php:
Ahora viene lo más difícil; necesitamos que cada uno de esos enlaces, al ser generado
dentro del bucle, obtenga de $fla[“id”] el código del registro que se está armando en ese
momento, y lo deje escrito dentro del enlace, en una variable que se enviará por el método
get hacia la siguiente página:
Visualmente, nada ha cambiado en los enlaces, pero si apoyamos el puntero del mouse
sobre cada una de las palabras BORRAR (sin pulsarlo, sólo deslizándolo por encima de cada
enlace), notaremos en la barra de estado, al pie y a la izquierda del navegador, que cada en-
lace además de apuntar hacia borrar.php, al ser pulsado enviará también la variable “código”
con su correspondiente valor.
Notemos que si pasamos el mouse sobre las distintas palabras BORRAR a lo largo
de todos los renglones, veremos que en cada renglón el valor de la variable “codigo” es di-
ferente, ya que se corresponde con el valor de $fla[“id”] de cada registro. De esta manera,
la página de destino podrá saber cuál es el registro que se desea eliminar, con total certeza.
Ahora, sólo nos resta el fnal: crear la página borrar.php hacia la que apuntan todos esos
enlaces, que es la página que realmente borrará el registro cuyo id coincida con el indicado
en la variable “codigo”.
Dentro de la página borrar.php, deberíamos estar recibiendo desde el listado anterior la varia-
ble “codigo”, que contiene el id de alguno de los registros, el que se desea borrar.
Por supuesto, deberemos validar si ha llegado al servidor y si no está vacía.
Esto se podría hacer de la siguiente manera:
<?php
} else {
Notemos que el valor va entre comillas simples, como todos los valores que en-
viamos hacia MySQL, y también notemos el agregado de una condición WHERE. Esta
condición es imprescindible en el caso de una orden DELETE, ya que permite restringir
la aplicación de la orden a apenas uno o varios registros que cumplan con esa condición,
en caso contrario, de no especifcar ninguna condición, borraríamos todos los registros
de la tabla completa.
Atención: esta orden es la más peligrosa del lenguaje SQL: DELETE FROM tabla; Al no
poseer una condición WHERE, elimina todos los registros de la tabla especifcada.
Por lo tanto, siempre que hagamos un DELETE agregaremos un WHERE para limitar
los registros que se eliminarán. En este caso, deseamos eliminar solo uno, aquel registro que
en el campo id posea el valor especifcado en la variable “codigo”, variable que el usuario ha
enviado desde el listado al pulsar “ese” enlace, el correspondiente a “ese” registro que desea
borrar.
Por lo tanto, en este ejemplo, nuestra orden SQL quedaría así armada:
Orden que colocaremos, como siempre, dentro de una variable llamada $consulta. Pero
ahora nos surge un ligero inconveniente: al envolver entre comillas dobles el contenido com-
pleto de la variable, entrarán en conficto con las comillas dobles que envuelven a “codigo”.
Tenemos dos maneras de remediarlo:
• Envolver entre llaves el valor que se enviará a MySQL, es decir, la parte fnal
de la orden DELETE que está envuelta entre comillas simples, en este caso:
$_GET[“codigo”]
• O traspasar a una variable local (que no contiene comillas) el contenido de
$_GET[“codigo”].
En el primer caso (usando llaves), la variable $consulta quedaría así:
$codigo = $_GET["codigo"];
$consulta = "DELETE FROM empleados WHERE id='$codigo'";
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
// Nos conectamos:
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( mysql_query($consulta) ){
} else {
} else {
} else {
}
echo '<p>Regresar al <a href="listado.php">listado</a></p>';
?>
Esto ya está listo para que lo probemos, y eliminará el registro que le indiquemos al
pulsar un enlace cualquiera del listado.
esa palabra se convierta en un enlace, que envíe un código hacia una nueva página que crea-
remos que se llamará modifcar.php. Esto no nos debería resultar un problema: es lo mismo
que hemos hecho antes para eliminar un registro, apenas cambia el nombre del archivo de
destino del enlace y la palabra que se mostrará:
Pero la complicación reside en que, para que el usuario pueda modifcar a su gusto los
valores de los campos, se requiere un paso adicional con respecto a la eliminación: no alcan-
za con saber el id del registro a “actualizar” únicamente, ya que no sabemos qué campos
de ese registro querrá actualizar el usuario, ni qué nuevos valores le querrá dar. Por lo tanto,
antes de actualizar, deberemos mostrar todos los datos de ese registro, pero dentro de atri-
butos value de campos de un formulario, para que aparezcan escritos sus valores actuales
y, una vez que el usuario modifque libremente lo que está viendo en su pantalla, esos datos
deberán ser enviados hacia otra página PHP, que estará esperando estos nuevos valores
en el servidor, y esa es la página que realmente ejecutará la orden de actualizar los valores de
ese registro en la base.
Figura 13-9. Pedido de un formulario con los datos incluidos, listos para editar.
Esta consulta, una vez ejecutada con la función consultar que creamos con el objeti-
vo de ejecutar órdenes SELECT (algo muy sencillo a estas alturas) nos traerá datos de una
sola fla de la tabla, los que deberemos asignar a un “paquete” que llamaremos típicamente
$datos.
El código de esta página denominada modifcar.php hasta este punto, podría ser el
siguiente:
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
// Nos conectamos:
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( $paquete = consultar($consulta) ){
} else {
} else {
} else {
Ahora, crearemos una función que llamaremos editarRegistro, cuya tarea consistirá
en cargar los valores de cada campo del registro seleccionado dentro de atributos value de
campos de un formulario.
Para ello, la función necesitará recibir como parámetro el paquete de datos denomi-
nado $paquete, y deberá extraerlo a una matriz (que típicamente llamaremos $fla), usando
la conocida función mysql_fetch_array, tal como hicimos en el listado inicial, pero con una
ligera variante: esta vez no será necesario un bucle, ya que la consulta sin duda traerá “un solo
registro” (es imposible guardar dos o más registros con el mismo id en una tabla cuyo campo
id fue declarado como clave primaria).
Por lo cual, ejecutaremos lo que sigue una sola vez:
$fla = mysql_fetch_array($paquete);
Y ya tendremos cargada la matriz $fla con los datos completos de ese registro, tal
como estaban guardados en la tabla.
<?php
function editarRegistro($datos){
} else {
$codigo = false;
return $codigo;
}
?>
Ahora, viene la parte más complicada: nuestra función debe generar un formulario
HTML que dentro de sus campos muestre escritos todos los datos que actualmente están
dentro de la matriz $fla.
Veamos cómo hacerlo.
La forma más cómoda de crear este formulario es generar su código mediante un
editor de HTML, cuidando que su atributo action apunte hacia una página (que todavía no
hemos creado) que llamaremos modifcado.php.
Ese formulario contendrá cinco campos input de tipo text (no cuenta el campo id por-
que no permitiremos que sea modifcado), y un botón para enviar.
En cuanto hayamos creado con nuestro editor el código HTML de este formulario, lo
pegaremos dentro de nuestra función editarRegistro, inmediatamente después de haber
traspasado a $fla el contenido de $datos.
Pegaremos el código del formulario dentro de la variable $codigo, cuyo valor lo delimita-
remos con comillas simples (debido a las abundantes comillas dobles que deben envolver
los valores de los atributos en el código HTML). Nuestra función por ahora va quedando así:
<?php
function editarRegistro($datos){
<p>
<label>País:
<input name="pais" type="text" />
</label>
</p>
<p>
<label>Especialidad:
<input name="especialidad" type="text" />
</label>
</p>
<p>
<input type="submit" name="Submit" value="Guardar cambios" />
</p>
</feldset>
</form>';
} else {
$codigo = false;
return $codigo;
}
?>
Esto es apenas un código básico como para comenzar. No nos olvidemos que este
formulario debe mostrar escritos, dentro de cada campo, los valores del registro que se
modifcará, que ya los tenemos almacenados dentro de la matriz $fla. Si queremos, pode-
mos probar de incluir una llamada a esta función dentro de nuestra página modifcar.php, así
vemos cómo muestra el formulario (aunque vacío). Éste será el código defnitivo de la página
denominada modifcar.php:
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
// Nos conectamos:
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( $paquete = consultar($consulta) ){
echo $resultado;
} else {
} else {
} else {
Si en el listado pulsamos alguno de los enlaces que dicen MODIFICAR, por ahora ve-
remos el formulario vacío:
Volvemos a nuestra función editarRegistro. Para escribir los datos que faltan dentro del
formulario, deberemos ir concatenando los distintos campos de $fla dentro de los atributos
value de cada input. Antes de hacerlo, los traspasaremos a variables locales, para evitar
problemas con las comillas; de paso, codifcaremos en UTF-8 los datos traídos de la base:
$nombreActual = utf8_encode($fla["nombre"]);
$apellidoActual = utf8_encode($fla["apellido"]);
$edadActual = $fla["edad"]; // La edad es un número
$paisActual = utf8_encode($fla["pais"]);
$especialidadActual = utf8_encode($fla["especialidad"]);
<label>Nombre:
<input name="nombre" type="text" value="'.$nombreActual.'"
/>
</label>
</p>
<p>
<label>Apellido:
<input name="apellido" type="text"
value="'.$apellidoActual.'" />
</label>
</p>
<p>
<label>Edad:
<input name="edad" type="text" value="'.$edadActual.'" />
</label>
</p>
<p>
<label>País:
<input name="pais" type="text" value="'.$paisActual.'" />
</label>
</p>
<p>
<label>Especialidad:
<input name="especialidad" type="text"
value="'.$especialidadActual.'" />
</label>
</p>
<p>
<input type="submit" name="Submit" value="Guardar cambios"
/>
</p>
</feldset>
</form>';
Ahora sí, veremos los datos actuales escritos dentro de cada campo, listos para ser
modifcados por el usuario:
Figura 13-12. El formulario de edición con los datos actuales cargados en cada campo.
Pero este formulario, tal como está programado hasta este momento, sólo enviará hacia
modifcado.php las variables “nombre”, “apellido”, “edad”, “pais” y “especialidad”. ¿Cómo
sabrá, entonces, la orden SQL que ejecutaremos en esa página fnal (modifcado.php) –que,
desde ya, contendrá un WHERE–, a cuál registro debe actualizar los datos? Buena pregunta.
Hasta ahora, no tendrá forma de saber qué registro hay que actualizar.
Deberemos hacer que este formulario envíe también el código (id) del registro que se
actualizará. Entonces, agregaremos un campo input más, pero que, a diferencia de los otros,
no será completado por el usuario, sino que su valor lo defniremos nosotros mismos dentro
de un campo oculto (un input de tipo hidden), al que le pondremos como name “codigo”, y
cuyo value lo escribiremos usando el valor del código que estamos editando, o sea, el que en
esta página tenemos almacenado aún dentro de $fla[“id”]).
$codigoActual = $fla["id"];
Con esto, nuestra página modifcar.php queda terminada y, nuestra función editarRe-
gistro, también.
Pasemos ahora a codifcar la última página, modifcado.php, que es la que fnalmente
ejecutará la orden SQL que actualizará los valores actuales y los cambiará por los nuevos
valores ingresados por el usuario en el formulario que acabamos de crear.
En nuestro ejemplo, luego de traspasar a variables locales todos los datos que se hayan
recibido de la matriz $_POST, la orden UPDATE quedaría así:
<?php
// Incluimos los datos de conexión y las funciones:
include("conexion.php");
include("funciones.php");
if ( isset($_POST["nombre"],$_POST["apellido"],$_
POST["edad"],$_POST["especialidad"],$_POST["codigo"]) ){
// Nos conectamos:
if ( conectarBase($host,$usuario,$clave,$base) ){
if ( mysql_query($consulta) ){
} else {
} else {
} else {
que “le pertenece” (sus pedidos, sus mensajes, sus tareas, etc.). Éste es el front-end. Las
páginas por las que navega el usuario.
Vamos a tomar como ejemplo para analizarlo paso a paso (sin codifcarlo) un sistema
de pedidos, en esta ocasión, para el sitio Web de una Pizzería. Será muy fácil reutilizarlo con
ligeros cambios para otros tipos de negocio, ya que el circuito de recepción de un pedido
suele tener muy pocas variantes entre un negocio y otro.
El front-end será utilizado por los clientes para hacer su pedido, y el back-end será utili-
zado por el operador que modifca el estado del pedido, carga productos, actualiza precios, etc.
Necesitaremos comenzar haciendo un listado de las tareas que cada tipo de usuario
realizará (podemos mostrarlas visualmente como diagramas de casos de uso). Luego, de
estos casos de uso deduciremos qué páginas será necesario crear para navegar por cada
caso de uso, y cuáles serán las principales funciones que será preciso defnir. Deduciremos
cuántas tablas tendremos que crear en la base y cuáles serán los principales campos y sus
tipos de dato.
id TINYINT
producto VARCHAR
descripcion TEXT
url_imagen VARCHAR
rubro ENUM (pizza, empanada, postre, bebida)
precio FLOAT
id INT
nombre VARCHAR
domicilio VARCHAR
telefono VARCHAR
comentarios TEXT
con_cuanto_paga VARCHAR
importe FLOAT
codigo SMALLINT
fecha DATE
estado ENUM (recibido, en preparación, en
camino, entregado, anulado)
Pensando técnicamente qué parte del proceso de ABM realizará el usuario de un for-
mulario de pedido, primero verá la lista de productos. Para ello, realizará un SELECT. Luego,
verá un formulario y, al enviarlo, realizará un INSERT en la tabla de pedidos. Dará de alta un
registro. Después, si desea consultar el estado de su pedido, entrará en un formulario y, al
enviarlo, hará un SELECT.
Lo podemos esquematizar mediante un diagrama de casos de uso:
En este diagrama, incluimos la tarea de consultar el estado del pedido, cosa que reali-
zará el usuario en las páginas pedir-estado.php y ver-estado.php, introduciendo en la primera
de ellas el código que le fue generado al realizar el pedido.
Pasemos ahora del otro lado del mostrador.
más antiguo, o aquellos que tengan como estado “en espera”) y cambiar el estado de un
pedido.
Clase "teléfono"
Propiedades Métodos
La clase “teléfono” de este ejemplo es tan teórica como los vertebrados o mamíferos;
en la naturaleza no existe ningún animal concreto que sea sólo un mamífero, sino distintas
aplicaciones reales (en programación, instancias) de mamíferos: un perro, una vaca, etc.
A su vez, la clase “perros” permitirá tener dentro otras clases que serían las distintas ra-
zas, y de una raza en particular, por ejemplo, Dobermann, se instanciará un perro específco.
Los individuos (instancias) son los objetos que realmente “existen”; el resto (mamíferos,
perros, dobermanns) son sólo construcciones teóricas, “clases” de objetos, cada una con
características cada vez más particulares a medida que nos alejamos de la clase padre inicial.
Los individuos, en programación, se llaman objetos o instancias, y siempre se crean
a partir de una clase declarada previamente que defne sus características.
Al programar de esta manera, crearemos una clase que sirva para un propósito en
particular, y luego podremos generar “objetos” instanciados a partir de esa clase, que harán la
tarea para la que fue creada, más cualquier agregado especial que le queramos hacer como
individuos particulares.
Otro ejemplo:
Pensemos en una clase llamada “enviaMails” que genere formularios capaces de enviar
correos electrónicos. El objeto que se creará será el formulario así que, para concebir la
clase, debemos concentrarnos en las características (propiedades) y funcionalidades (méto-
dos) de un formulario.
Nuestra clase necesitará cierta información imprescindible para poder cumplir con su
objetivo que es enviar mensajes. Por ejemplo, un campo donde escribir un remitente, un
destinatario, un asunto y un mensaje. Si le proporcionamos estos datos, deberá ser capaz de
ejecutar la funcionalidad de despachar un correo electrónico.
Por única vez, nos tomaremos el trabajo de defnir las propiedades y los métodos uni-
versales de la clase y, de allí en más, nuestra tarea se habrá facilitado en gran medida y, cuan-
do precisemos un formulario que envíe mails desde un sitio, crearemos una “instancia” (un
objeto) de esta clase “enviaMails”, que tendrá las características básicas mencionadas (y, tal
vez, otras especiales, únicas de esta instancia que se nos ocurran tales como, por ejemplo, la
posibilidad de mandar mensajes a celulares o la de mantener una agenda de contactos, etc.).
En el futuro, al tener que hacer en otro sitio Web un sistema de envío de mails, simple-
mente volveremos a instanciar la clase “enviaMails” que hemos creado, agregándole otras
funciones extra diferentes si fuera necesario, pero siempre ahorrándonos rehacer el cuerpo
principal de características y funcionalidades generales.
$patas = 4 ;
$cola = "cortada";
$color = "negro";
$fuerza = "mucha";
En cambio, los métodos de una clase se corresponden con las cosas que es capaz de
hacer la clase (son “verbos” en infnitivo): volviendo al ejemplo del perro, serían correr, morder,
comer, saltar, defender, atacar, saludar, mover la cola, etc.
En programación tradicional se relacionan con el concepto de funciones, pero con la
característica de que, en realidad, los métodos son acciones que modifcan alguna pro-
piedad del objeto en cuestión. Por ejemplo, el método “correr” modifca las propiedades
“latitud” y “longitud” del perro, es decir, su posición en el planeta.
Entonces, hablando técnicamente, las clases son “paquetes” de propiedades y
métodos.
Veamos una primera clase bastante simplifcada (la idea no es hacerla funcionar sino
reconocer sus partes):
<?php
class Formulario {
private $campo;
public $codigo;
function __construct(){
print "Esto es el constructor de la clase
Formulario";
}
function mostrarFormulario(){
return($this->codigo);
}
function enviarCorreo($destino, $asunto, $mensaje,
$remite)
{
$this->campo[0]= $destino;
$this->campo[1]= $asunto;
$this->campo[2]= $mensaje;
$this->campo[3]= $remite;
return($this->campo);
}
}
?>
La clase continúa, no funciona, está incompleta, se utiliza aquí con fnes didácticos.
Observemos los siguientes detalles:
1. La clase se defne anteponiéndole la palabra class al nombre que le daremos (el
nombre, en singular y con la primera letra en mayúscula), y luego abriremos una
llave:
class Formulario {
3. Luego se declararán los métodos que podrán utilizar los objetos creados a partir
de esta clase, que no son más que funciones declaradas de la misma manera
a la que estamos acostumbrados (también se les puede anteponer alguno de los
modifcadores de visibilidad: public, private o protected, aunque en este caso no
lo hayamos incluido).
function __construct(){}
function mostrarFormulario(){}
4. Notemos que cuando en el cuerpo de los métodos nos referimos a las propieda-
des (las variables que hemos defnido), para darles un valor, lo hacemos mediante
la palabra $this-> y, a continuación, el nombre de la variable sin el signo $ (porque
ya lo tiene $this):
$this->codigo='';
La palabra $this hace referencia a “este objeto”, esta instancia, la que está ejecu-
tando el método. Decir $this->patas = 4 es lo mismo que decir: “adjudicar el valor
4 a la variable ‘patas’ de este objeto de la clase ‘perro’ en el que estamos”.
5. Observemos un detalle: el primer método de la clase se llama __construct; este
nombre lo convierte en un método constructor de objetos; es decir, que en
cuanto creemos un objeto instanciado de esta clase, se ejecutará automática-
mente este método constructor, asignándole valores a algunas de sus propieda-
des y haciendo que ya tenga disponibles ciertos métodos listos para usar en esa
nueva instancia “recién nacida”:
function __construct(){}
<?php
include("formulario.class.php");
// La clase siempre va en un archivo aparte. Es el código
que analizamos recién.
$miFormulario = new Formulario();
?>
<?php
include("formulario.class.php");
echo $miFormulario->codigo;
?>
<?php
include("formulario.class.php");
$miFormulario->campo[0] = "pepe";
?>
<?php
include("formulario.class.php");
$miFormulario->enviarCorreo("lector@libro.com",
"Saludos","Te mando saludos",
"hernan@beati.com.ar");
?>
Veamos, ahora sí, un ejemplo completo, que funcione realmente; llamemos a este ar-
chivo alCuadrado.class.php:
Para crear una instancia a partir de esta clase, en otro archivo llamado calculador.php
incluiremos la clase y crearemos un objeto a partir de ella:
Ahora bien, no siempre vamos a dejar el 4 allí, ya que necesitamos enviar datos a nues-
tro objeto. ¿En qué momentos le podemos pasar un dato a la clase, para que lo utilice en
alguna operación?
En los casos que se describen a continuación:
1 . Al crear el objeto, con su método constructor.
2. Al ejecutar otro cualquiera de sus métodos.
3. O defniéndole una propiedad que luego sea usada por un método.
1) Veamos la primera alternativa (al ejecutarse automáticamente el método constructor):
Archivo alCuadrado.class.php:
<?php
class alCuadrado {
private $numero;
function __construct($cifra){
$this->numero = $cifra;
}
function calcularCuadrado(){
return ($this->numero * $this->numero);
}
}
?>
Archivo calcular.php:
<?php
include ("alCuadrado.class.php");
$cantidad = 1 0 ;
/* Número a elevar (también podría llegar desde un
formulario o enlace que envíe variables a esta página). */
Archivo calcular.php:
<?php
include ("alCuadrado.class.php");
3) La tercera forma es que le defnamos una propiedad que luego será usada por un
método:
Archivo alCuadrado.class.php:
<?php
class alCuadrado {
public $cifra;
function calcularCuadrado(){
return ($this->cifra * $this->cifra);
}
}
?>
Archivo calcular.php:
<?php
include ("alCuadrado.class.php");
$resultado->cifra = 4 5 ;
/* Aquí le defnimos una propiedad como si fuera
una variable interna, de alcance local. */
El problema con esta última operación es que estaríamos violando una de las reglas
más básicas de la programación orientada a objetos: la ocultación de los datos internos
en una especie de “caja negra” a la que sólo se puede entrar mediante la ejecución de los
métodos de una clase. Desde el código de nuestra página no se debería dar un valor a una
propiedad (como tampoco se debería leer el valor de una propiedad directamente: sería me-
jor usar algún método creado a tal efecto). Para estas tareas sumamente comunes (dar un
valor y leer el valor de una propiedad), aprenderemos, a continuación, a crear métodos que
tendrán siempre la misma estructura, y que se denominan getter (traedor, lector), y setter
(defnidor). Veámoslos en detalle.
Método setter
Por el contrario, la estructura de un método setter, sí debe recibir un parámetro obligatoria-
mente, que será el valor nuevo que se le asignará a la propiedad en cuestión. No devolverá
nada con ningún return, simplemente le dará un valor a la propiedad:
A partir de ahora, será normal identifcar los métodos getter o setter a simple vista, por
su estructura: si un método no tiene parámetros y devuelve el valor de una propiedad, es un
getter. Si tiene un solo parámetro y se lo asigna a una propiedad, sin hacer ningún return, es
un setter.
De todos modos, es importante que evitemos caer en un error común: defnir un getter
y un setter a todas las propiedades de un objeto, puesto que iría contra la idea principal de
la OOP, que es “esconder” la mayor cantidad de términos de información de los objetos que
sea posible.
Para este objetivo, cuyo propósito es diferenciar los datos a los que se puede acceder
desde una instancia y a los que no, defnimos, al momento de crear a cada una de nuestras
propiedades, uno de los modifcadores de visibilidad: public, private o protected. Veremos en
detalle cuáles son las consecuencias de esta operación.
Defniendo la visibilidad
Pública
Cualquier método o propiedad, si no especifcamos nada, tiene por defecto visibilidad “pú-
blica”. También podemos especifcarlo explícitamente, si le anteponemos la palabra public.
De ambas formas, su valor podrá ser leído y defnido desde una instancia cualquiera de esta
clase o, incluso, desde fuera de ella (que es útil sólo en casos muy concretos). Esto equival-
dría, por ejemplo, a defnir variables dentro de una función como globales, o a leer variables
globales desde dentro de la función: una práctica poco recomendable.
Debemos tratar de limitar al mínimo la cantidad de “propiedades” defnidas como
public. Por el contrario, es normal que muchos de los “métodos” sí sean defnidos como
public. Serán los métodos ofrecidos por la clase para interactuar con ella. Se los llama su
interfaz: son los métodos públicos que una clase propone para que le envíen mensajes
desde el mundo exterior. Son su “control remoto”, las palancas y los botones desde los
que le hacemos hacer cosas a nuestro objeto.
Privada
En cambio, deberíamos tratar de defnir la mayoría de las “propiedades” con visibilidad
private; es decir, privadas, para que sólo desde dentro de la clase donde está defnida
la propiedad, pueda ser leída. Al estar defnida como private, se podrá leer igualmente por
todos sus métodos (incluso aquellos que sean públicos, como los getter y los setter que
estudiamos anteriormente).
No solo las “propiedades” pueden ser private, también se puede indicar que tengan vi-
sibilidad privada algunos “métodos”, para que los use exclusivamente la clase que los defnió.
Protegida
Por último, existe la posibilidad de declarar propiedades o métodos como protected (prote-
gidos), con lo cual, además de poder acceder a ellos desde la clase que los defnió, también
podremos hacerlo desde una clase “hija” o “padre” de la que los defnió (esto nos lleva al tema
siguiente: la herencia entre clases).
La idea de fondo de la OOP es defnir primero unas pocas clases muy generales, y luego
ir derivando, de esas primeras clases, otras clases cada vez más especializadas.
<?php
class alCuadrado {
public $numero;
function elevaAlCuadrado(){
return ($this->numero * $this->numero);
}
}
function elevaAlCubo(){
return ($this->elevaAlCuadrado() * $this->numero);
}
$cubo->numero = 3 ;
// Podría recibirse desde una variable
Atributos de clase
Uno de los últimos conceptos que veremos (para que podamos reconocerlo cuando lo vea-
mos implementado en las clases que usaremos) es el de los atributos de clase. Es decir,
defniremos atributos que no serán atributos de una “instancia” (objeto) de la clase, sino de la
clase misma, para su uso interno.
Constantes
Uno de estos posibles atributos de clase son las constantes. No llevan signo $ delante del
nombre, y su valor debe ser constante (un número, una cadena de caracteres), es decir, no
puede ser fruto de una variable ni de una operación matemática, ni de una llamada a una fun-
ción. Una típica constante, similar a las que ya sabemos defnir en PHP con la función defne.
Por ejemplo, el usuario y la contraseña de la base de datos.
Se declaran anteponiendo la palabra const a la propiedad y se leen anteponiendo self::
a la propiedad.
Veamos ejemplos:
<?php
class Base {
const usuario="root";
const clave="clave";
function getUsuario(){
return self::usuario;
}
function getClave(){
return self::clave;
}
}
echo $base->getUsuario();
echo "<br / > " ;
echo $base->getClave();
?>
Static
Otro de los posibles atributos de clase es static. Se utiliza para anteponerlo a cualquier pro-
piedad o método, para que luego pueda ser utilizado sin que sea necesario crear una instan-
cia de la clase.
Al usarse sin crear una instancia, no se utiliza $this ni el operador fecha ->, sino que
se antepone el nombre de la clase y luego se emplea el operador de resolución de ámbito (o
doble dos puntos, más simple) ::, que ya hemos visto en el ejemplo anterior.
<?php
class Prueba {
echo Prueba::empresa;
?>
No solo una propiedad puede ser static, también un método puede serlo:
<?php
class miClase {
miClase::estatizar;
?>
Versiones anteriores
En versiones de PHP anteriores a la 5, existen algunas diferencias en la forma en que se pro-
grama con orientación a objetos, de las cuales sólo vamos a mencionar un par, las más co-
munes, ya que nos encontraremos a menudo con ellas en cuanto comencemos a descargar
clases de libre uso, que hayan sido programadas con la sintaxis de PHP 4.
El primer punto clave es que en PHP 4 no existían los modifcadores de visibilidad.
Todas las propiedades y todos los métodos eran públicos. En vez de anteponerles public,
private o protected, en PHP 4 se les anteponía la palabra var:
<?php
class unaClaseAntigua {
var $nombre;
}
?>
<?php
class unaClaseAntigua {
function unaClaseAntigua(){
// etc...
}
}
?>
Otro sitio con clases (aunque no tantas como el anterior) es PHPSnaps: http://www.
phpsnaps.com
Vamos a utilizar uno de estos sitios para lograr un objetivo en muy poco tiempo, gracias
a la potencia de las clases pre-armadas: colocaremos un mapa de Google en nuestro sitio
usando una clase hecha por otro programador.
Una vez elegida la clase que usaremos, debemos estudiarla analizando “qué hace”
cada método, y cuáles son los parámetros que es necesario conocer para utilizarlos.
Manos a la obra.
Vamos a intentar encontrar alguna clase que muestre mapas de Google. Para ello,
usaremos el buscador interno de PHPClasses, y escribiremos “Google Maps”. Como resul-
tado, obtendremos no sólo las clases relacionadas con mapas de Google, sino con sitemaps
de Google, que no es lo mismo. Por lo cual, aquí hacemos nuestra primera selección, y
las candidatas se reducen: sólo los cinco primeros resultados parecería que hacen lo que
necesitamos:
Entramos al primero de los resultados, la clase llamada “Karatag Google Maps HTTP
Request” y leemos su descripción: sirve para enviar una dirección y obtener como respuesta
sus coordenadas geográfcas (latitud y longitud). Muy interesante, pero no es lo que busca-
mos ahora.
Pasamos al segundo resultado: la clase llamada “N/X API to Google Maps”. Leemos
su archivo about.txt y nos explica que el archivo que contiene la declaración de la clase es
nxgooglemapsapi.php y que el resto son ejemplos (lo cual es muy bueno, siempre nos con-
viene utilizar clases que vengan con ejemplos de uso).
Nos recuerda además que, para utilizar Google Maps, precisamos obtener una clave
de Google. En el archivo readme.txt vuelve a insistir que, para que esto funcione, debemos
conseguir una clave de Google y escribirla en la parte del archivo nxgooglemapsapi.php que
dice:
Así que, ante todo, deberemos registrarnos y obtener una clave para que Google nos
permita utilizar su API (Application Programming Interface, o Interfaz de programación de
aplicaciones). Lo podemos hacer entrando a:
http://code.google.com/intl/es-ES/apis/maps/signup.html
Una vez que obtuvimos la clave, la ingresamos en esa línea de la clase, por ejemplo:
defne(GoogleMapsKey, 'ABQIAAAAoM-kEW8yHxWwveOZAouVXhTkQdzC1
XuexHlQDsWmu58XcfHJ8xQB-xtA9nt_7NDWTsfJfHHxosdNZg');
Figura 14-4. Envolvemos entre comillas los nombres de las constantes, sin incluir espacios en blanco.
$instancia->setWidth(800);
$instancia->setWidth(600);
• Nivel de zoom inicial: se defne con el método setZoomFactor, que agrega una
pequeña validación que nos indica el rango de valores permitidos: de 0 a 17:
$instancia->setZoomFactor(16);
• Agregar un marcador con una dirección escrita en formato natural, es decir: nom-
bre de calle y número, ciudad, país, y especifcando un mensaje que aparecerá
al pulsar el marcador sobre el mapa. Para esto, se usa el método addAddress:
El último parámetro booleano (true, en este caso), indica si esta dirección debe ser el
centro del mapa (obviamente, solo una dirección por mapa puede ser su centro).
• Agregar una ubicación sobre la base de sus coordenadas: addGeoPoint:
$instancia->addGeoPoint(19.4270499,-99.1275711,'Mexico
DF',true);
$instancia->setCenter(19,-90);
$instancia->addControl(GLargeMapControl);
$instancia->addControl(GSmallMapControl);
$instancia->addControl(GSmallZoomControl);
$instancia->addControl(GScaleControl);
$instancia->addControl(GMapTypeControl);
$instancia->addControl(GOverviewMapControl);
Todos estos valores de constantes deben ser indicados (como vimos en example1.php)
como valores del único parámetro del método addControl. Por eso reiteramos que resulta
tan importante que leamos cada uno de los métodos, para ver qué hacen, qué parámetros
necesitan recibir, cuáles son los valores posibles y qué consecuencias tienen.
En los archivos example3.php y example4.php, podemos seguir investigando otras fun-
cionalidades, como la de movernos hasta un punto al pulsar en un enlace, o incluir un campo
de búsqueda que nos permita ingresar una dirección y nos devuelva sus coordenadas (algo
muy útil cuando precisamos saber las coordenadas de un lugar).
Hemos logrado nuestro objetivo de agregar un mapa en muy pocos minutos, gracias a
haber tomado como punto de partida una clase creada por otro programador.
Luego de nuestra primera aproximación a esta nueva forma de programar, si queremos
seguir profundizando en la sintaxis y lógica de la programación orientada a objetos, como
siempre, recomendamos revisar el manual ofcial de PHP: http://www.php.net/oop
Ahora, ya estamos en condiciones de ir todavía un nivel más arriba, y aprender a utilizar
sistemas enteros listos para usar, que es de lo que hablaremos en el siguiente capítulo del
libro.
“Un enano subido a los hombros de un gigante, verá más lejos que
el mismo gigante”
Refexionemos un momento sobre el modelo de desarrollo del
software libre, para que podamos evaluar las ventajas y desventajas
de utilizar sus proyectos como punto de partida de los nuestros.
Con lo que ya sabemos programar en PHP, nada nos impide
programar un sistema completo desde cero, identifcando las tareas
principales que deberán realizar los usuarios de ese sistema (casos
de uso), y creando páginas, funciones y/o clases para lograr todas las
interacciones necesarias con una base de datos. Pero, con el tiem-
po, luego de haber pasado repetidamente por la experiencia de crear
sistemas desde cero, notaremos que buena parte de los sistemas se
suelen parecer bastante entre sí. Llegará un punto en el que pensa-
remos que no inventaremos nada nuevo, puesto que casi todo está
hecho.
Por lo tanto, en vez de programar todo desde cero en cada nuevo proyecto, será más
efciente disponer de un conjunto de soluciones ya probadas y perfeccionadas, y solamen-
te “adaptarlas” a cada uno de nuestros clientes. Usaremos como base para nuestro trabajo
lo que muchos otros programadores experimentados han creado, y si le encontramos alguna
falla, compartiremos la solución (o, al menos, avisaremos cuál fue la falla, para que otro le
encuentre solución). De esa manera, el sistema se irá perfeccionando con el tiempo, y cuando
volvamos a implementarlo para otro cliente, disfrutaremos de las soluciones que hemos ido
aportando todos los usuarios en nuestro testeo cotidiano.
Al usar un sistema libre, al igual que hicimos con las clases en el capítulo anterior, nues-
tra principal tarea será seleccionar el sistema que más se asemeje a lo que necesitamos.
Una vez elegido, analizaremos sus funciones, sus métodos, sus páginas, y lo adaptaremos
a las necesidades de nuestro cliente particular realizando pequeños retoques y agregados.
El comenzar nuestro trabajo a partir de una base que ya funciona, posee una serie inne-
gable de ventajas competitivas frente al desarrollo de sistemas a medida desde cero:
• Muchísima rapidez de desarrollo, plazos de entrega cortos.
• Presupuestos mucho más bajos: competitividad.
• Facilidad de adaptación.
• El conocimiento sobre el sistema está distribuido en una comunidad, por lo que
no se depende de un solo proveedor para que nos dé soporte y nos solucione
cualquier problema.
Como hemos visto en el primer capítulo del libro, nuestro mercado ideal es éste:
Hacer sistemas a
Adaptar sistemas
Decorar páginas (no medida desde cero
TAREA PRINCIPAL: prearmados rápida y
saben programar) (caros y de largo
económicamente
plazo)
NIVEL DE Decenas a centenas
Cientos Miles / Decenas de miles
PRESUPUESTOS: de miles
Desde ya que no competiremos con empresas de sistemas a medida, que manejan pre-
supuestos y plazos enormes, sino que apuntaremos a satisfacer las necesidades de peque-
ñas y medianas empresas, que con relativamente poca inversión y en muy poco tiempo,
podrán contar con un sistema Web funcionando efcientemente.
De nuestras capacidades (nuestras, o de las personas con las que nos asociemos para
integrar un equipo) dependerá agregarle valor, mediante la integración de diseño, multime-
dia y programación PHP, a estas soluciones prearmadas.
(literalmente) miles de proyectos libres, sistemas completos, listos para que los descargue-
mos gratuitamente, los adaptemos y los vendamos a nuestros clientes.
La clave está en el estilo de desarrollo colaborativo: esa modalidad crea grandes
comunidades de programadores en torno a cada proyecto, que se benefcian de aportar
apenas un granito de arena cada uno (reportar algún fallo, sugerir alguna mejora) y, a cambio,
utilizan el sistema completo cada vez más perfeccionado (tarea muy difícil para un equipo
de pocas personas trabajando aisladas dentro de una empresa de desarrollo de código
cerrado).
Dirección Comentarios
http://www.opensourcescripts.com/dir/PHP/ Casi 40 categorías de scripts PHP
Más de 60 categorías, pero muchas no son
http://osliving.com/
aplicaciones Web hechas con PHP.
Pulsando la opción “All CMS Demos” en la
http://php.opensourcecms.com/ columna izquierda, nos muestra más de 280
scripts.
http://www.scriptscenter.com.ar/category/ Pulsando “Scripts PHP”, o “Open Source”,
scripts-php/open-source-scripts-php obtendremos decenas de aplicaciones.
Como vemos, contamos con una variedad de proyectos para todos los gustos, listos
para ser descargados.
Por último (y es totalmente intencional haberlo dejado para el fnal), el criterio que para-
dójicamente menor importancia tiene a la hora de elegir este tipo de sistemas es la calidad de
la codifcación (uso de versiones nuevas de PHP, uso de OOP). Ya que de nada sirve la mejor
calidad inicial, si el proyecto no logró convocar una comunidad de programadores que hagan
avanzar el proyecto y publiquen contribuciones, parches de seguridad, etc. Por supuesto, lo
ideal es que se unan una gran comunidad y un buen código.
Una vez descomprimido en una carpeta de nuestro servidor (nosotros lo hemos colo-
cado en una carpeta llamada weblog), abriremos con nuestro editor el archivo wp-confg-
sample.php, y escribiremos los datos de conexión a nuestra base.
Atención: debemos tener ya creada de antemano una base de datos con ese nombre,
para que, al continuar la instalación, se puedan crear las tablas necesarias. Si estamos
trabajando localmente, iremos al phpMyAdmin y crearemos una nueva base; si estamos
en un hosting, usaremos las herramientas que ofrezca para crear una base (o utilizaremos
una base existente).
Una vez ingresados los datos de conexión, deberemos escribir frases diferentes en toda
esta zona:
http://localhost/weblog/wp-admin/install.php
Allí, luego del texto de bienvenida, veremos la siguiente pantalla, donde deberemos
cargar los datos que nos solicita:
Una vez ingresados, nos dirá que ya tenemos instalado nuestro blog. Ahora, nos pide
que nos identifquemos para comenzar a administrar el contenido de nuestro nuevo sitio:
Una vez identifcados, quedaremos frente al panel de administración, desde donde pue-
de confgurarse casi todo.
Con estos simples pasos, ya tenemos un sistema de weblog funcionando. Ahora, va-
mos a comenzar con las modifcaciones.
Modifcaciones básicas
Una vez que nuestro sistema esté funcionando, la lista de modifcaciones que podemos rea-
lizar es muy extensa, pero debería incluir al menos estos aspectos:
1. Modifcar el diseño: elegir un theme (plantilla), cambiando la imagen, los colores y
estilos CSS, y agregarle widgets.
2. Confgurar las categorías en las que clasifcaremos los textos que publicaremos, y
agregar los primeros textos.
3. Por último, agregar “contribuciones” (plugins), o programar a mano modifcaciones
a las funcionalidades existentes.
Veamos rápidamente los cambios más fáciles de realizar:
1. Para elegir otra plantilla de diseño, en el panel de administración, iremos al menú
izquierdo, pulsaremos donde dice Apariencia Temas y, luego, en la solapa
superior que dice Instalar temas.
Allí podremos seleccionar temas por varios criterios: color, cantidad de columnas,
tipo de ancho (fjo o fexible), características especiales, y asunto del sitio (para qué
tipo de contenidos es). También podemos navegar por los más Destacados, o por
los Recientes.
Una vez elegida la plantilla que nos guste, podemos previsualizarla pulsando en
Vista previa, y también instalarla en nuestro weblog con el enlace Instalar que
cada miniatura de diseño tiene debajo:
2. Pasemos al segundo punto: para confgurar las Categorías en las que agrupare-
mos nuestros contenidos, dentro del panel de administración vamos a Entradas
Categorías:
Una vez elegido alguno de los candidatos (en este caso, elegiremos “WP Google
Weather”), pulsamos en Instalar ahora:
WP Gco
WP Google Weather M W w " M *W 3 ' e Weather displays a Weather Widget in your sidebar or on single pages/posts
Features
Detalles
show today's weather
show weather forecast for next 3 days
specifíy output language
choose between Celsius or Fahrenheit
supports shortcodes for single pages or posts
comes with predefined CSS style
vahd XhTML output Por Hendnk Wtll.
Descomprimiendo...
Instalando el plugin...
Notemos que por cada plugin instalado, existe una carpeta dentro de /wp-content/
plugins/
En este caso, la carpeta de nuestro plugin se llama wp-google-weather. Dentro de
esa carpeta encontraremos una hoja de estilos (desde donde podremos modifcar los colores,
3. Por último, si ya hemos colocado nuestra función y nuestro “gancho”, sólo resta
activar el plugin y ubicarlo en la página desde el panel de administración.
Vamos a hacerlo, paso a paso:
Empecemos creando la función que leerá las frases desde un archivo de texto (para
simplifcar, no hemos usado una base de datos), elegirá una al azar y la mostrará:
<?php
function muestrafrases(){
$frases = fle($archivo);
shuffe($frases);
?>
Ahora, el segundo paso: crear un enganche (hook) entre nuestra función y alguno de
los eventos que se van sucediendo en WordPress.
Por ejemplo, el evento podría ser el instante en que se inicializan todos los widgets:
add_action('widgets_init', 'muestrafrases');
Esa llamada a add_action debe estar colocada en el mismo archivo que la declaración
de nuestra función, pero fuera de ella.
<?php
add_action('widgets_init', 'cargar_frases');
function cargar_frases(){
register_widget('muestrafrases');
}
// Método constructor:
function muestrafrases() {
}// fn de muestrafrases
$instance = $old_instance;
return $instance;
}// fn de update
function form($instance) {
// Confguración de valores por defecto para el
widget
$defaults = array( 'title' => __('Ejemplo',
'example'), 'lang' => ' e s ' , 'alignment' => false ) ;
$instance = wp_parse_args( (array) $instance,
$defaults ) ; ?>
<p>
<p>
<label for="<?php echo $this->get_feld_id(
'lang' ) ; ?>"><?php _e('Idioma:', 'lang'); ?></label>
<input id="<?php echo $this->get_feld_id(
'lang' ) ; ?>" name="<?php echo $this->get_feld_name( 'lang' ) ;
?>" value="<?php echo $instance['lang']; ?>" size="2" />
</p>
<p>
<input class="checkbox" type="checkbox"
<?php if($instance['alignment'] == true) echo 'checked';
?> id="<?php echo $this->get_feld_id( 'alignment' ) ; ?>"
name="<?php echo $this->get_feld_name( 'alignment' ) ; ?>" />
<label for="<?php echo $this->get_feld_
id( 'alignment'); ?>"><?php _e('Alineación centrada?',
'alignment'); ?></label>
</p>
<?php
}// fn de form
/**
* Cómo mostrar el widget en la pantalla.
*/
function widget( $args, $instance ) {
extract( $args ) ;
$lang = $instance['lang'];
$alignment = $instance['alignment'];
if($alignment == true) {
$alignmentclass = 'centered';
}
$frases = fle($archivo);
// A $frases lo convertimos en una matriz con tantas
celdas como líneas -renglones- tenía el archivo de texto.
echo ("<p>".$frases[0]."</p>");
echo '
</dl>
</div>
<div style="clear: both;"></div>
';
}
function replaceChars($data){
$search = array('Ä', ' Ö ' , ' Ü ' , ' ä ' , ' ö ' , ' ü ' , ' ' ) ;
$replace = array('Ae', 'Oe', 'Ue', 'ae', 'oe',
'ue', ' % 2 0 ' ) ;
$output = str_replace($search, $replace, $data);
return $output;
}
}
add_shortcode('muestrafrases', 'mostrar');