Sunteți pe pagina 1din 88

bsicos

Los secretas de
PHP y MYSQ./.;

------r-----
r,-=--'":.- - "F
.......

Bases de datos
SQL, MySQL
I_ Gestin de bases .de datos con phpMyAdrnin

Prctica
Crea un lburn de fotos y
un rnini CMS

-----
Nmero 30--,-tos secretos de PHP y MYSQL 5,00 EUR
2 PC Cuadernos

n
Secretos t
s

de impressions
a

PHP y intercomarcals,
S.A. San! Fruits

MySQL de Bages,
Barcelona
Johann-Christian Distribucin
Hanke quioscos:
C
Copyright: o
KnowWare EURL e
d
Traduccin: Victria
i
Mengual PC s
Cuadernos - Bsicos
S
www.pc- .
cuadernos.com
L
Sociedad .
editora: Avda. de
KnowWare Barcelon
a, 225
E.U.R.L.
M
70, rue
o
Georges Villette l
F-77250 i
n
Ecuelles s
Francia
Director: Mikkel d
e
Franck
Direccin R
e
electrnica: i
info@pc-
B
cuadernos.com
a
Depsito legal: B- r
22770-2006 c
ISBN: 2- e
915605-46-7 l
o
Im n
pr a
en
ta: Vent
a
l por
m nm
p eros
ri :
Despus de su aparicin, los nmeros Con "Secretos de PHP y MySQL",
de esta coleccin pueden pedirse por Johann- Christian Hanke nos trae la
correo. continuacin del cuaderno "PHP 5"
(Consulta la pgina 77) publicado anteriormente. En este
nuevo ttulo, el autor va ms all en
sus explicaciones y explora el
verdadero po- tencial del lenguaje
PHP cuando se utiliza
en combinacin con bases de datos.

El cuaderno empieza repasando los cam-


bios de sintaxis en las ltimas versiones de
1
1 PHP, hablando de las funciones propias y de
trucos de notacin que facilitan las cosas al
programador, adems de presentar la forma
de vincular archivos con el comando inclu-
de. Desde el punto de vista prctico, apren-
ders a cargar archivos a una pgina web
con ayuda de PHP.

Los siguientes captulos se centran en co-


nocer MySQL, la interfaz PHPMyAdmin y los
principales comandos SQL para consultar,
modificar, filtrar y eliminar tablas de bases
de datos. El autor incluye tambin una lista
con los principales tipos de datos y presenta
las distintas formas posibles de mostrar los
datos como HTML. Todo ello, sin olvidarse
de los formularios como herramienta para
introducir datos y del procedimiento para
crear copias de seguridad de tablas.

Al final del cuaderno se presentan dos pro-


yectos sumamente interesantes: un script
para enviar automticamente felicitaciones
de cumpleaos a tus conocidos (utilizando
un cronjob), y un completo proyecto para un
libro de visitas con fotografas, que se puede
modificar fcilmente para convertirlo en un
fotoblog o un sistema de gestin de conte-
nidos.

Mikkel Franck, editor.


mfranck@pc-cuadernos.com
Todos los productos citados en este manual son
marcas registradas o marcas comerciales. El au
tor y el editor declinan toda responsabilidad que
pueda surgir de la utilizacin de los datos o pro
gramas que aparecen en este libro.
Bienvenido al mundo de los sitios web dinmicos 3

Bienvenido al mundo
de los sitios web dinmicos
En este cuaderno seguiremos profundizando en Aprenders SQL, el lenguaje para crear, mante
PHP. Por fin est aqu la esperada segunda parte ner y consultar tablas de bases de datos. Con
de mi cuaderno titulado "PHP 5". A todos y to ayuda de una libreta de direcciones, te mostrar
das, bienvenidos, y me alegro de que este tema cmo:
siga despertando vuestra curiosidad e inters.
Crear tablas de una base de datos
Introducir datos
De qu trata el cuaderno? Presentar las filas deseadas
Incluir comandos SQL en PHP
Como no poda ser de otra forma, este cuaderno Y la prctica? En este caso he pensado que te
trata sobre PHP y MySQL. Te sonar a mucha gustara un libro de visitas realmente cmodo:
prctica, y de eso se trata precisamente. Pero con campo para incluir una fotografa, bloqueo
como siempre, antes de la prctica dte ofrecer contra reload y presentacin de los datos por
una racin de teora.
pginas. Tambin se puede utilizar como siste
ma de gestin de contenidos, weblog o fotoblog.
Tcnicas avanzadas de PHP
En la primera parte del cuaderno, hablaremos de Como calentamiento te presentar un pequeo
determinadas tcnicas de programacin avan "script de cumpleaos" que enviar automti
zadas. Entre otras cosas, veremos: camente a todos tus contactos una felicitacin
electrnica por su cumpleaos.
Nueva sintaxis desde PHP 4.2
Cmo escribir tus propias funciones Los lmites del cuaderno
Separacin de mdulos medante include() ... se encuentran en el diseo de bases de datos
Mtodos para que el cdigo sea ms legible relacionales, es decir, la vinculacin de varias ta
blas para hacer que el almacenamiento de datos
Naturalmente, probaremos tambin todas es sea ms efectivo. Hablaremos de ello por encima
tas novedades en la prctica: cargaremos ar de forma muy didctica y comprensible.
chivos desde un formulario y los guardare
mos en una pgina web. Adems, tambin Despus te remitir a otra autora, Petra Bilke. El
aprenders las distintas funciones partiendo motivo es que Petra ofrece en su cuaderno sobre
de ejemplos sencillos. "PHP y MySQL", publicado anteriormente, una
introduccin detallada a esta materia, y repetir
lo mismo sera como llevar lea al monte.
Despus de ocuparnos de esto, iremos al grano.
Nos pondremos con el tan esperado ...
Sobre el autor
Curso sobre MySQL y SQL No soy ningn programador genial, sino auto
didacta. Sin embargo, la programacin es mi afi-
Hablaremos de cmo configurar y utilizar
cin, a la que he dedicado muchas, muchas no
MySQL en tu proveedor de hosting, y cmo ma
ches y fines de semana. Puedes encontrar un
nejar bases de datos (o base de datos, ya que al
gunos proveedores solamente permiten usar
ejemplo en la pgina alemana www.phpkid.de. la
primera que logr crear controlada exclusiva
una).
mente con bases de datos.
Aprenders a utilizar la interfaz grfica de En la "concepcin" de este portal aprend mu
phpMyAdmin. chsimo, y estoy orgulloso de poder transmitir
los conocimientos adquiridos.
Y le seguirn los ejemplos. Pero antes de poner Te deseo todo el xito del mundo con "Secretos
nos con el primer ejemplo prctico de base de de PHP y MySQL".
datos, tambin es necesario un poco de teora.
4 Bienvenido al mundo de los sitios web dinmicos

Descarga de los archivos de


' ejemplo
Encontrars los archivos de ejemplos del cua
derno en el suplemento gratuito que se puede
descargar en lnea desde: http://www.pc-
cuadernos.com

JohannChristian Hanke

Quieres probar PHP y MySQL offline? Para


ello solamente necesitars un servidor web
local, que funciona a la perfeccin con PHP y
MySQL: se trata del servidor Apache. Para los
lectores del cuaderno anterior "PHP 5" no ser
nada nuevo, y por eso no quiero perder pgi
nas repitiendo los pormenores de la instala
cin y configuracin. En el cuaderno anterior
ya explicamos cmo instalar Apache y PHP
con el paquete XAMPP de Apachefriends
(www.apachefriends.org).
Si no tienes ningn conocimiento previo sobre
PHP, te recomiendo encarecidamente que leas
mi cuaderno anterior titulado "PHP 5". En el
cuaderno que nos ocupa, asumir que el lec tor
tiene unos buenos conocimientos bsicos

dePHP


La nueva sintaxis de PHP 5

La nueva sintaxis de PHP desde la


versin 4.1 4.2
Qu pena! As describira yo la aparicin de la Para el uso de PHP online, es decir, cuando se
primera edicin alemana del cuaderno "Intro
duccin a PHP", que termn de redactarse en trabaja con proveedores de Internet, esto si
abril de 2002. La ltima versin de PHP en esa gue sin suponer ningn "peligro". Hoy toda
poca era la 4.1, y cuando se public el cuader va hay muchos proveedores que todava no
no, todo pareca ir bien. han cambiado a register_globals = Off.
Sin embargo, poco despus de la aparicin de
ese ttulo (en junio de 2002) apareci una versin Incluso el propio XAMPP antepone la comodi
totalmente nueva de PHP: la conocida versin dad a la seguridad y no quiere molestar a los
4.2. Cmo lo supe? Por los muchos lectores que usuarios. En todas las versiones que he podido
me enviaron sus quejas por correo electrnico, probar, siempre se mantiene en "On".
diciendo que todos los ejemplos a partir del ca
ptulo 5 ya no funcionaban. Qu haba ocurri
do? Informacin sobre PHP
Sin vacilar, los creadores de PHP haban cam Cmo est configurado register_globals en tu
biado una variable de servidor en el archivo servidor local, o en tu proveedor? Comprubalo
utilizando la conocida funcin phpinfo ( 1. Como
de configuracin php.ini.
recordatorio: crea un documento con el siguiente
contenido, gurdalo como info.php y colcalo en
En lugar de register_globals "" On, la opcin la carpeta raz del servidor local o en tu pgina
predefinida pas a ser register_globals Off. web:
Ergo: la mayora de scripts dejaron de funcionar.
<?php
Esta verdad solamente es aplicable en el caso de phpinfo{);
una instalacin offline, por ejemplo, cuando se ?,
trabaja a mano o con FoxServ.
Por suerte, pronto pude tranquilizar a mis lecto r' J
res. Todos los ejemplos del cuaderno eran y si
guen siendo vlidos, siempre que se vuelva a
modificar la variable. En la segunda edicin on
alemana del cuaderno de principios de 2003, in
clu una nota sobre este problema, en la que re- XAMPP establece register_globals en on
comendaba volver a cambiar la variable de
C:\Windows\ php.ini a On: Mi consejo personal es que te acostumbres (poco
a poco) a la opcin off, porque la seguridad de
be anteponerse a la comodidad. En este cuader
no, programar exclusivamente en la nueva sin-
: regh'ter _g1obals to be on: ustng for variables taxis.
"9lob;11s can e.a:s1ly lead
; to posstb1e security prob1eu, tf the cod ts not
En algn momento todos los proveedores
IC':! "f.'ofof tambin cambiarn la variable y la establece
rn en off. Y cuando llegue ese momento, de
Jst..e.r11 f1 f j
; Whether or not to re;ts'ter the old-.st.yle input:
arrays, HTTP-<iET_VAAS
; and frtends. rf you"re not uslng thett, tt:'s
beras estar preparado.

Ha llegado la hora de cambiar de mtodo, pero


En aquel entonces, el archivo php.ini se sola encon antes te explicar por qu es mejor la nueva sin
trar en C: \ Windows; pero si trabajas con la herra taxis. Despus te presentar el agujero de segu
mienta de instalacin XAMPP presentada aqu, lo ridad valindome de un ejemplo, tras el cual se
encontrars en xampp/apache/bin. guro que convendrs conmigo en que es necesa
rio bloquear la creacin automtica de variables

/.
6 La nueva sintaxis de PHP
globales. No importa si utilizas la versin PHP No importaba si el formulario se enviaba por
4.x o PHP 5.x. method= "post" o met.hode "get Incluso era po
11

sible determinar el valor de las cookies utilizan


do el nombre de las mismas. Una cookie llamada
Como reza el dicho: safety nombre se converta en una variable llamada
$nombre.
first! Admito que esta forma de escribir era y es muy
cmoda. Demasiado cmoda! De un lado, es
Qu quiere decir exactamente que de golpe ya
posible que cree confusin. Imagina que has
no estn permitidas las "variables globales" (re
creado un campo de formulario llamado nnme, y
gister_globals)? Qu son las variables globales?
casualmente tienes una cookie con el mismo
Variables globales nombre en el cdigo fuente. En ese caso, a travs
de Sname se acceder tanto al contenido del
Las variables globales registradas abarcan los campo de formulario corno al valor de la cookie.
datos de 11GET11 y "POST", "COOKIE" y Quin ganar? Depender del script.
"SERVER"; es decir, prcticamente todas las Es cierto que podramos ahorramos todos estos
fuentes de variables externas. Estos valores ya problemas desde el principio. Basta con asignar
no estn disponibles de forma global. Dicho una abreviatura slo a las cookies o a los campos
de otra forma: los datos de dichas fuentes ya de formulario.
no se pueden leer directamente mediante
"$nombredevariable". Las cosas se ponen ms feas en el caso del c
digo programado "a lo chapucero". Ensegui
da te mostrar las consecuencias que puede
Ejemplo con anlisis de formularios tener.
Si la explicacin anterior te ha parecido dema
siado tcnica, te mostrar el principio paso a pa
so con un ejemplo. Empecemos con el anlisis de Cdigo fuente del archivo inseguro.php
formularios y la arra y $_POST. Observa el cdigo que aparece a continuacin.
Cpialo y gurdalo corno inseguro.php. Abre el
Hasta ahora, PHP era muy sencillo. El nombre archivo en el navegador.
de un campo de formulario se converta autom
ticamente en variable. As, el valor de un campo 1 Puedes identificar el agujero de seguridad?
de formulario corno:
<input type="text" name:"Nombre"> (Naturalmente, para que el ejemplo funcione,
Se poda consultar de esta forma: asumo que register_globals sigue todava en On
en tu servidor local).
echo "<b>$Nombre</b>", bienvenido cP
a mi sitio\n";

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">


<html>
<head>
<title>El gran agujero de seguridad</title>
<meta http-equiv=11content-type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h2>Agujero de seguridad en register_globals = On</h2>
<form action="<?php echo 11inseguro.php11; ?>" method="post>
Contrasea: <input type="password" name="pass">
<input type="submit" value=11Enviar">
</form>
<?php
if ($pass "abc_xyz_123")
$login= true;

if ( $login) {
echo "<p>Aqui empieza el rea secreta.</p>11;
La nueva sintaxis de PHP 7

?>
</body>
</html>

Resumen del cdigo fuente Establecer register_globals en off


Estoy trabajando con la variable $login. Su valor En este curso, te recomiendo sin dudarlo que
debera ser true slo si se conoce la contrasea trabajes siempre con register_globals desactivado.
correcta. Slo tienes que cambiar el valor en el archivo
php.ini a Off Cmo puedes hacerlo?

'TZ" I . f;
if ($pass == "abc_xyz_12311)

, r 11,;.
$login= true;
1:... r
Desafortunadamente, no he inicializado la va l. En primer lugar, comprueba dnde se en
riable con false desde el principio. Por causa de cuentra php.ini, XAMPP no utiliza la ruta
esta pequeo descuido en el cdigo es posible
que cualquiera que no conozca la contrasea vea C:\ Windows, sino una ruta de acceso propia.
lo que no debera ver. Cmo?
Slo tendra que agregar ?login=true o ?login=1 a
la URL. Porque 1 significa true. En ese caso, la
php.ini
variable $login pasara a ser true y se abrira la
"puerta" al rea secreta. 2. XAMPP suede utilizar, por ejemplo,
C:\xampp(lite)\apache\bin\php.ini. Detn el

----
Prubalo: abre el archivo inseguro.php escribien servicio XAMPP y abre el archivo php.ini.
do: inseguro.php?loginml!
.. . . .
E ii:J c>;a ..-- -?
3. Busca la lnea register_globals = On (no tiene
que tener un punto y coma delante, ya que
punto y coma equivale a comentar el cdi
login=11 go).
Agujero de seguridad en register_globals = On 4. Sustituye On por Off y guarda el archivo ini.
5. Inicia otra vez XAMPP y comprueba la con
figuracin.

-
Podemos entrar sin saber la contrasea.
Prueba nuevamente el truco de login. Ya no fun-
ciona, de modo que hemos cerrado el agujero de
seguridad.

I Es una situacin dramtica, verdad? Otras novedades


Matrices $_POST y $_GET Desde 2003 ya se hablaba mucho de PHP 5. De
Los creadores de PHP reconocieron este proble hecho, los primeros libros sobre PHP 5 aparecie
ma de seguridad, y lo solucionaron con PHP 4.1: ron mucho antes de que surgiera PHP 5.
Todos los datos de formularios enviados me Sin embargo, las capacidades mejoradas (pero
diante method="post" se guardan en la array, no necesariamente suficientes) en relacin con la
$_POST. programacin orientada a objetos slo son inte
Los datos de metlwd="get" se almacenan en la resantes para verdaderos expertos. PHP es un
array $_GET. Entre ellos tambin se cuentan lenguaje de scripts. En nuestro caso, el trabajo
los parmetros transmitidos a travs de la orientado a objetos sera como disparar a go
URL. rriones con caones. Y, teniendo en cuenta que la
mayora de proveedores siempre van por detrs
Si deseamos acceder al valor de "?login=true" de las ltimas versiones con meses o incluso
aadido a la URL, slo podremos hacerlo desde: aos de retraso, personalmente actuara con pru
$_GET ['login'] . dencia.
Por lo tanto, esta es la variante ms segura, y por
ese motivo deberas dejar definitivamente regis
ter_globals en Off.
8 La nueva sintaxis de PHP
Las novedades realmente interesantes para la todas las que se pueden reconocer con la funcin
gente que se inicia en la programacin se intro phpinfo(). A nosotros nos interesan sobre todo el
dujeron en la versin PHP 4.1. A partir de esta nombre de archivo y la ruta de acceso.
versin, adems de las arrays ya mencionadas
Anteriormente, cuando queramos determinar la
$_POST y $_GET tambin se presentaron las
arrays asociativas: ruta y el nombre de un archivo, escribamos
$PHP_SELF. Segn la nueva sintaxis, ahora slo
$ COOKIE se puede acceder a este valor mediante
$_SERVER['PHP_SELF'].
Esta array contiene todas las variables de una
cookie. Con $_COOKIE{'visita'J podemos deter
minar, por ejemplo, el valor de la cookie visita. Ejercicios sobre la nueva
$ REQUEST
Esta arra y juega un papel especial. Contiene to
sintaxis
dos los valores de $_POST, $_GETy $_COOKIE. La prctica hace al maestro, as que a continua
Puede resultar prctico cuando el script recibe
cin te propongo un par de ejercicios.
tanto datos procedentes de un formulario como
datos que hayan sido transmitidos mediante un
parmetro de la URL de la pgina anterior.
Ejercicio 1: variable de servidor
Integra la variable de servidor
Por tanto, podramos acceder al valor del campo $_SERVER['PHP_SELF'] en el archivo insegu
de formulario ro.php y sustituye la variable $pass por la varian
<input type="text" name="Nombre"> te $_POST. Encontrars mi solucin en insegu
ro2.php.
tanto si el formulario se enva mediante
met.hodevpoat;" como method=' get.
1
Ejercicio 2: comparacin en cdigo fuente
Sin embargo, soy muy prudente en el uso de Compara ambas variantes; la que indica direc
$_REQUEST, ya que suele limitar ligeramente tamente el nombre del archivo y la que utiliza la
los esfuerzos para un mayor "orden". variable de servidor. Analiza el cdigo fuente de
la pgina generada por el servidor.

-
Con estas nuevas variables, desaparecen las
antiguas denominaciones de arrays previas a
la versin PHP 4.1:
>Al;<1j.eii,11 de t:"l.d.ad <!la ,:.eql.u-i,_qlc)bals - 0&</11.2>
<rcl'JJ "'QtLOJI,'""'/_.Php2/1cGUrCl2 .pllp MtM<l"'"'pollt."'>
$HTIP_POST_VARS Ci:nti,:c.,..l1 <1apai: -Pworo .--HJr"'>
<t.ispoi:: r:vP,$-t v.Al.G6-?n.v1ar">
$HTIP_GET_VARS ,,.....,.
<Ita no

,C:/htlll>
$HTTP_COOI<IE_VARS
Acostmbrate a usar $_POST, $_GET y El servidor web siempre enva un archivo HTML al
$_COOI<IE! navegador; en vano buscars los comandos de PHP.
Qu diferencia puedes observar?
Tambin son nuevas las variables de arrays
$_SERVER, $_ENV y $_SESSION. $_ENV es res Ejercicio 3: inicializar variables
ponsable de las variables de entorno y Arregla mis chapuzas del ejemplo "inseguro".
$_SESSION se encarga de la gestin de sesiones. Asegrate de que no quede ninguna puerta
Hablaremos de las sesiones en un futuro tercer abierta a los mirones, incluso aunque regis
cuaderno dedicado a PHP. ter_globals est activado. Encontrars la solucin
en el archivo inseguro3.php.
La variable $_SERVER
Sin duda, la ms interesante es la variable
$_SERVER, ya que contiene todas las variables
de servidor, es decir, todas las variables que
transmite el servidor web. El servidor transmite
Trucos de notacin 9

Trucos de notacin que hacen la vida


ms fcil con PHP
Puedo confesarte algo? En la escuela me consi No se muestra el contenido de la variable, sino la
deraban un bicho raro. En lugar de ir a la disco string $_POST['Nombre'). No sirve de nada
teca, iba a clase de msica, y en lugar de por el tomar en consideracin la regla de utilizar comi
ftbol, me interesaba por la arquitectura, la lite llas desiguales cuando se anidan varias comillas.
ratura y la fotografa. Si todo el mundo crea que
solamente A poda ser correcto, yo me obstinaba Para la clave de la array utilic a propsito comi
en buscar una alternativa llamada B o C que tu llas simples, y las dobles nicamente fuera. Pero
viera exactamente el mismo resultado. no me sirvi de nada. Hay que concatenarlas.
echo "Hola ebo " . $_POST ['Nombre'] &
De forma parecida me sent con PHP cuando "</b> ! ";
ocurri todo el tema de "register_globals = Off"
y el cambio a la nueva sintaxis. No poda con Qu complicado! En aquellos casos en los que
haya numerosas variables, el asunto se puede
formarme con la idea de que la notacin me
complicar muy rpidamente.
diante las arrays $_POST, $_GET o $_REQUEST
tuviera que volverse tan complicada. El truco es el siguiente:
Te mostrar un par de trucos que he descubierto Olvdate de las comillas que habitualmente
mediante prueba y error. Pocas veces los encon rodean la key.
trars en los libros para principiantes o en los
scripts de muestra de Internet, donde suele pre
El ejemplo anterior pasara a tener este aspecto:
dominar la forma de escritura "complicada".
echo "Hola <b>$_POST[Nombre)</b>!";
Pero, por lo que puedo ver, mis trucos son fia
bles y, ante todo, funcionan de primera. Adems, Esta notacin sin comillas solamente se puede
no provocan ningn mensaje de error. utilizar cuando la propia variable est contenida
dentro de un par de comillas dobles. En todos
Con respecto a los mensajes de error: dentro los dems casos, debers rodear siempre la key
de dos pginas pondremos en prctica un "es con comillas simples o dobles, segn prefieras. Y
tricto" sistema de gestin de errores. siempre debers hacerlo tal como te he mostrado
en $_POST['Nombre'].

No hay ninguna diferencia si el pasaje detrs


El truco de las arrays de echo utiliza comillas simples o dobles, ya
que las variables de dicho pasaje solamente se
A primera vista, la escritura mediante la nueva interpretarn como variables si se utilizan
sintaxis de arrays se vuelve ms complicada. Se comillas dobles.
gn la antigua sintaxis, podramos acceder al si
guiente campo de formulario
<input type="text" name="Nombre">

de forma simple y sencilla, y seguir trabajando


Un segundo truco para las
con l:
echo "Hola <b>$Nombrec::/b>!";
arrays
No era necesario concatenar las strings con las Hay otro truco ms: coloca la variable dentro de
variables. Era un idilio perfecto: texto, etiquetas un par de signos de llave. De este modo, pode
HTML y variable, todo unido mediante un solo mos utilizar para la key las comillas simples o
par de comillas. dobles:
Conforme a la nueva sintaxis, las cosas ya no echo "Hola <b>{$_POST('Nombre']}</b>l";
son tan sencillas. Prueba el siguiente cdigo y En este cuaderno utilizaremos siempre esta no
quedars admirado: tacin, y no slo con $_POST, $_GET o
echo "Hola <b>$_POST['Nombre']</b>!11 ; $_REQUEST, sino tambin con otras arrays.
10
Pasajes largos con echo. truco 1
Trucos de notacin A modo de ejemplo, observa el cdigo fuente
que se presenta a continuacin. Dado que no se
pueden anidar las comillas del mismo tipo, utili
zamos el signo de escape \.

Si hay algo que siempre me ha irritado es la


complicacin a la hora de escribir el cdigo
cuando, utilizando PHP, se quieren mostrar pa
sajes largos en H1ML con echo.

echo "<form action=\"mail.php\" method=\"post\">\n";


echo 11<input type=\"hidden\" name=\"Mail\" value=\"$ POST(Mail]\">\n";
echo "<input type=\ "hidden\ name e', "mensaje\" value=\ "$ POST [mensaje] <Y
\">\n";

As es como aparece en muchos libros y como lo El truco para hacerlo ms fcil es:
encontrars en la mayora de scripts. Cmo es
posible que tantos autores (incluido un tal Sr. En lugar de comillas dobles, utiliza siempre
Hanke en el cuaderno "Introduccin a PHP") se comillas simples.
hayan complicado tanto la vida ...
Este sera el mismo cdigo fuente modificado:

echo "<form action='mail.php' method='post'>\n";


echo "< input type= hidden' namee 'Mail' val ue= $_POST [Mail J > \n" ;
echo "<input type .. "h.i dden ' nameermeneaj e ' value='$_POST[mensaje] '>\n";

Es totalmente vlido, ya que no hay ninguna re Si compramos diez productos en el supermerca


gla que diga que en H1ML es obligatorio utilizar do, no los llevamos a casa uno a uno, sino que
comillas dobles para los valores de los atributos. los metemos todos en una sola bolsa y "trata
mos" la compra como si fuera una II coleccin".
Pasajes largos con echo, Lo mismo es aplicable a echo:

truco 2 Escribe la instruccin echo una sola vez. Colo


ca todas las lneas de HTML que desees mos
No contento slo con eso, se me ocurri qu pa trar en un par de comillas dobles. Para divi
sara si quisiera mostrar diez lneas de H1ML dirlas entre ellas, utiliza saltos de lnea.
una tras otra. Tendra que utilizar diez veces
echo y escribir diez pares de comillas? Por qu? El cdigo pasara a tener el siguiente aspecto:

echo ".:::form action=mail.php1 method=='post'


<input t ypee t h .dden ' name='Mail' value='$_POST[Mail] '>
<input type='hidden' name='mensaje' value::'$_POST[mensaje] '>\n";

Lo mejor de todo es que podemos ahorramos


escribir los molestos caracteres \n (new line). Pasajes en sintaxis heredoc
Mediante los saltos de lnea se crear automti
Tienes remordimientos de conciencia? Quieres
camente una "instruccin de new line",
seguir usando comillas dobles en los atributos
(Solamente he sangrado el cdigo para que ten de H1ML y tampoco ests preparado para re
ga mejor aspecto y para mostrar la correspon nunciar a las comillas simples o dobles alrede
dencia con echo). dor de las keys?
Trucos de notacin 11
Tampoco te convence lo de usar un solo echo la sintaxis heredoc. Lo mejor es que analices el
para varias filas? En ese caso, tengo otra alterna cdigo que se presenta en el siguiente ejemplo.
tiva, que tampoco es muy conocida, as que ser La cuestin es: ves las diferencias?
toda una sensacin. En qu estoy pensando? En

echo <<<FORMULARIO
<form action="mail.php11 method="post">
<input t ypeevh .dden" narne e vNa i.L'' value:::11{$_POST[1Mail1]}">
1
<input t ypeevhd.dden" name="mensaje" value= 11 {$_POST ['mensaje ]} u>
FORMULARIO;

Sintaxis heredoc a fondo Acceso a variables


En primer lugar, observars que de esta forma es Dado que se trata de un prrafo HlML conven
posible mostrar prrafos HlML convencionales, cional, seguro que te estars preguntando cmo
"no editados". El truco radica en esta estructura acceder a los valores de las variables.
peculiar:
Muy sencillo, recurriendo al truco que ya hemos
echo <<<FORMULARIO
visto anteriormente:
Con este operador se introduce el rea heredoc.
Recuerda que detrs de la palabra clave FOR
MULARIO no se puede escribir ningn punto y
l Rodea las variables con un par de llaves:

coma. Para cerrar el prrafo heredoc, se utiliza: value= 11 {$_POST [ 'Mail']}"

FORMULARIO;
Observa que la palabra termina con un punto y En lugar de utilizar la instruccin echo, po
coma; en este caso es necesario escribirlo sin es
demos almacenar la string de la instruccin
pacio en blanco para cerrar correctamente el rea
heredoc en una variable. En ese caso, en lugar
heredoc.
de:
Naturalmente, podras utilizar cualquier otra
echo <<<FORMULARIO
denominacin ms corta o sencilla para FOR
MULARIO. Sin embargo, no debers utilizar es escribiramos
pacios en blanco ni caracteres especiales, ni
$variable= <<<FORMULARIO
acentos ni nmeros al principio. Asegrate de
que esta palabra clave especial no aparezca en
ningn otro punto del cdigo fuente.
Identificar todos los errores
Con la palabara heredoc se abrevia el pasaje
"here document", que en espaol sera: aqu Es bueno saber que PHP nos avisa cuando hay
empieza el documento. Dentro del par here un error en el cdigo. Pero sabas que de forma
doc se puede escribir cdigo H1ML conven predeterminada PHP slo muestra determina
cional, sin ms complicacin. dos errores? Siempre se muestran las adverten
cias y errores fatales, pero los avisos sencillos
(notice) no se ven. He aqu un ejemplo de un
aviso sobre una variable no definida:
Notice: Undeflned variable: db In
C:\xampplite\htdocs\inde,c.php en llne 120
Warning mysql_close(): supplled argument ls nota va.lid MySQL-
Llnk resource In C:\,campplite\htdocs\lnde,c.php on llne 120 j
Un aviso (notice) tambin proporciona informacin
interesante.
12 Trucos de notacin

Este tipo de avisos podran ser especialmente


tiles, ya que te advertirn sobre las "chapuzas"
de programacin que cometas. Por ese motivo te
recomiendo que los actives:
l. Abre el archivo php.ini, tal como ya hemos
visto en la pgina 7.
2. Busca esta lnea:
error_reporting = E_ALL & -E_NOTICE

3. Elimina & E NOTICE:


error_reporting = E_ALL

A partir de ahora vers todos los errores.

Debugger de PHPEdit: Me imagino que


habrs observado que el editor de PHP
PHPEdit (www.phpedit.com), del que ya
hablamos en el cuaderno "PHP 5", tiene un
potente debugger de cdigo integrado. Para
usarlo, basta con seleccionar la opcin de me
n Debug I Runo presionar la tecla [F9]. Po
drs ver los mensajes de error directamente
en el editor, sin tener que abrir primero la p
gina. PHPEdit es un gran programa.
Separar cdigo con include() 13

Ms comodidad y seguridad: separar


cdigo con include()
Analicemos una vez ms el ejemplo de cdigo pecto de tu cdigo actual debera ser el siguiente
del principio, el de consulta de la contrasea. Ya (slo muestro el cdigo contenido entre <body>
lo hemos modificado y adaptado a la nueva sin </body>):
taxis. Si has superado todos los escollos, el as

<h2>Agujero de seguridad en register_globals = 0n</h2>


<form action="<?php echo $_SERVER[1PHP_SELF'l; ?:>11 method=post">
Contrasea: <input type=11password11 name="pass">
<input type="submit" value:11Enviar">
</form>
<?php
$login= false;
if (isset($_POST['pass']) && $_POST['pass'] "abc_xyz_l2311) {

$login = true;

if ($login) {
echo 11<p>Aqui empieza el rea secreta</p>";

?,

Sin embargo, este ejemplo todava presenta dos En la mayora de proveedores de alojamiento
"agujeros de seguridad": existe una de estas carpetas no accesibles al
La contrasea se puede leer directamente en pblico, y se llama cgibin. Comprueba si tu
el cdigo del archivo PHP. proveedor de alojamiento ofrece una carpeta
El rea secreta tambin se encuentra en el cgbn y cul es su ubicacin exacta. Si no ex
propio archi YO PHP. iste, slo tienes que crearla directamente utl"
zando un programa FTP.
Y cul es el problema? Al fin y al cabo, el servi
dor web nunca muestra el cdigo PHP tal cual.
El usuario siempre recibe una pgina HTML Comprueba con un archivo HTML si los archi
"montada", en la que se ocultan todos los pasa vos almacenados en dicha carpeta estn real
jes secretos. mente protegidos:

Y qu ocurrira si PHP dejase de funcionar en


tu proveedor de Internet? Si bien es cierto que
no es una circunstanca habitual, qu ocurri
ra si se da? "' Acceso prohibido!
U5kd no liene permiso pera axt'SIII' la m'ea:in soliciada. Eme &
En ese caso, la pgina PHP ya no se interpretar, que DO ois&a 1ii doamenlacia requerida_
sino que se mostrar "directamente". Y las con
traseas y los datos secretos no tendrn nada de
secretos, se podrn ver directamente. XAMPP tambin bloquea el acceso a la carpeta cgi
bin
Por ese motivo, cualquier programador profe
sional se atiene a una regla bsica: las contrase Ha funcionado en tu caso? Fantstico. Esta car
as o datos de acceso deben guardarse en archi peta estar cerrada a "personas ajenas", y cual-
vos externos. Dichos archivos no deben encon quier dato que se guarde en ella no ser accesi
trarse en carpetas accesibles al pblico. ble directamente para el usuario. Sin embargo,
con un script se puede (en la mayora de los ca
14 Separar cdigo con include()
sos) acceder a los datos almacenados en dicha Si deseamos vincular prrafos PHI', el archi
carpeta. vo en cuestin deber incluir etiquetas de
PHI':
<?php
Sintaxis de la funcin
include()
?>

A estos "archivos inc" con cdigo PHI' se les


Y aqu es donde entra en juego la funcin inclu suele asignar la extensin inc.php.
dei). Gracias a esta interesante funcin es posible Ya basta de charlas. A continuacin, te mostrar
vincular da tos externos y analizarlos. el aspecto del ejemplo de cdigo anterior en
include ("ruta/archivo. ext") nuestra variante con include.
Entre parntesis se debe indicar la ruta de acce Cdigo fuente de password.inc.php
so, el nombre del archivo y la extensin. Rodea
toda la string con un par de comillas. En primer lugar, veamos el cdigo fuente del ar
chivo password.inc.php, que he colocado en la
Recuerda las siguientes reglas: carpeta /cgibin:
Mediante include() se desactiva automtica
mente la notacin PHP. Por tanto, el archivo
a vincular se considerar siempre como un
archivo de texto o HTML normal.

<?php
$pw "abc_xyz_l23";
?>

Aqu no ocurre nada ms que la declaracin de En tu proveedor online puedes utilizar rutas que
la contrasea, en forma de variable $pw. partan de la carpeta raz:
Guarda este archivo en la carpeta cgibin. de tu /cgi-bin/password.inc.php
servidor. Normalmente, dicha carpeta (si existe) En mi prueba offline con XAMPP, no ha funcio
se encuentra directamente debajo de la raz. Para nado con este segundo mtodo.
probarlo offline, tambin tendrs que crear una
carpeta cgibin directamente dentro de la raz de En caso de dudas, lo mejor es volverlo a in
XAMPP (htdocs). tentar. Ajusta la ruta de acceso. Te dars cuen
ta enseguida cuando aparezcan mensajes de
Ruta al archivo include error.
Cul es la ruta de acceso al archivo include?
En mi ejemplo, el archivo inseguro se encuentra El siguiente paso es modificar el cdigo del ar
dentro de/_php2. Por tanto, primero debo subir chivo "inseguro". Vincula el archivo de la con
un nivel( .. ) y despus entrar en la carpeta cgi trasea y sustituye la contrasea por la variable
bin. La ruta de acceso completa es: $pw: funciona? Encontrars mi solucin en el
archivo inseguro4.php:
.. /cgi-bin/password.inc.php

<?php
$login= false;
include(11 /cgi-bin/password.inc.php11 );
if {isset($_POST[1pass1]) && $_POST[1pass] $pw) {
$login= true;

if {$login) {
echo 11<p>Aqu empieza el rea secreta</p>11;
Separar cdigo con include() 15

Vincular un archivo HTML Ejercicio sobre proteccin


Para terminar, todava falta el "fea secreta".
Bastar con vincular un archivo HTML conven
con contrasea
cional, pero nicamente si lo guardas en la ca
Esta parte slo contiene un ejercicio. Remodela
repta segura cgibin. (Ya que, de lo contrario,
remos la proteccin con contrasea de forma
cualquiera que conozca la direccin directa po
dria acceder a los datos). que se pidan tres contraseas y se muestren tres
pginas distintas. De este modo podrs asentar y
Modifica la segunda consulta if del archivo "in practicar los conocimientos que ya tienes (del
seguro" de la siguiente forma: curso anterior).
if ($login) {
include(" .. /cgi-bin/secreto.html"); Ejercicio: mltiples contraseas
Las tres contraseas del ejemplo son a?ix201,
La pgina secreto.html no contiene ninguna eti a?ix202 y a?ix203.
queta en PHP. Basta con utilizar lneas HTML Para el anlisis del formulario, utiliza la instruc
sencillas: cin switch. Analizaremos el campo pass, y ade
<hl>Top Secret</hl> ms he introducido las contraseas en los pun
<P>Esta es el <b>rea secreta</b>.</p> tos correspondientes para hacerlo ms claro.
Compralo con el archivo inseguroS.php. Como recordatorio, este es el aspecto de una ins
truccin switch clsica.
Mayor seguridad con una extensin falsa switch {$_POST[1pass1]) {

Puedes probar un truco ms para lograr una case "a?ix201":


mayor seguridad. Para ello, tendrs que asignar echo II rea secretal" ;
a la pgina secreta una extensin distinta de break;
html, por ejemplo gif.
case a?ix202":
11

Vincula la pgina de la siguiente forma: echo rea secreta2" ;


if ($login) { break;
include {" .. /cgi-bin/secreto. gif") ;
case "a?ix203":
echo rea secreta3";
Si, por algn motivo, un usuario puede abrir la break;
pgina directamente, como mnimo sta no se
mostrar. Al fin y al cabo, el navegador espera default:
echo 11<p>Introduce una centrase-
que se trate de un archivo de imagen y se negar a!</p>";
a cargar el documento como archivo de texto.
Sin embargo, la funcin include() hace caso omi Sin embargo, no tiene que quedarse as!
so de esta extensin "incorrecta".
l. Guarda las tres contraseas en el archivo
Compara el cdigo con el archivo del suplemen pw.inc.php dentro de cgibin y gurdalas en
to inseguro6.php.
las variables $pw1, $pw2 y $pw3.
Seguiremos utilizando la teenologfa include a 2. Vincula este archivo correctamente en la p
lo largo del cuaderno. De un lado, la utiliza gina de peticin de la contrasea.
remos para guardar los datos de contraseas
3. Guarda tambin los tres archivos HTML en
MySQL. Del otro, trabajaremos con "mdu
la carpeta cgibin y vinclalos de forma ex
los", es decir, fragmentos de texto que des
terna. Llmalos secretol.gif, secreto2.gif y se
pus reaprovecharemos.
creto3.gif. (Extensin gif'.)
Encontrars la solucin en el archivo multi
pw.php.
16 Escribir funciones propias

Escribir funciones proplas


Ya has recorrido un buen trecho para convertirte Por lo general, una funcin suele devolver un
en un profesional de PHP. En este captulo ve valor, que puede ser un nmero, una cadena o
remos un tema muy importante, que por moti un valor como true o false ..
vos de espacio no pude tratar en el cuaderno an
terior: el de las funciones. Por qu funciones propias?
Hay ocasiones en las que PHP no ofrece ninguna
Las funciones son mdulos de programas que
funcionalidad ni hay posibilidad de que lo haga
estn a nuestra disposicin.
en el futuro. En estos casos, deberemos escribir
nuestras propias funciones.
Ya hemos hablado de muchas de las funciones
integradas en PHP. Sabemos comprobar la fecha Las funciones propias presentan una ventaja:
y la hora con date(), dar formato a cadenas de mientras que las funciones predefinidas son una
texto con sprintj() o comprobar la versin de especie de "black box" (slo vemos el resultado
PHP con phpi nfo(). y no sabemos cmo PHP llega hasta l), en el ca
so de las funciones propias somos nosotros
La funcin isset($Variable) comprueba si existe quienes definimos con total precisin lo que
una variable y devuelve true o false en funcin ocurre con los argumentos y qu valor se de
del resultado. vuelve.
El objeto que se comprueba se suele denominar Puedes guardar tus propias funciones a buen re
tambin argumento. caudo y utilizarlas nicamente cuando las nece
Una funcin puede tener uno o varios argu sites.
mentos. Los argumentos se separan mediante
comas. Sintaxis de las funciones
Pero antes de crear nuestra primera funcin,
veamos la sintaxis bsica:

function Nombrefuncion(Argurnento[, Argumento])


{
Lineacodigo(n);
return $Valorvariable;

Llaves Nombres de las funciones


Como se puede observar, el bloque de la funcin Lo mismo que ocurre con los nombres de las va
est contenido entre un par de llaves. riables es aplicable a las funciones: deberemos
evitar los espacios en blanco, los caracteres espe
A diferencia de la notacin de if, while o far, ciales y diresis, y no deben empezar por un
la gente de PEAR recomienda esta forma de nmero. Se distingue entre maysculas y mi
es cribir el cdigo. De este modo, la llave de nsculas.
abertura y la de cierre siempre tienen reser Se suele utilizar mucho el cdigo tipo "camello".
vada una lnea de cdigo propia. En el caso de funciones cuyo nombre contenga
varias palabras, se escribe la segunda (y tercera)
En este caso, adems, se trabaja con una sangra palabra en mayscula, a fin de mejorar la legibi
del texto de cuatro caracteres. lidad.
Por ejemplo, escribe miNuevaFuncion () .
Escribir funciones propias 17

Un ejemplo: de bruto a neto


Convertir bruto a neto
Hace muchos aos, hice un ridculo espantoso
en un curso de informtica. Como profesor, na
turalmente. Se trataba de calcular el valor neto c1.1c::6 , I Caleuta, 1
partiendo del valor bruto, y en lugar de ello, yo 100.00
trat el valor bruto como si fuera el neto.

En Espaa, la mayora de productos que se El valor neto se calcula mediante una funcin
compran estn gravados con un impuesto so
Tambin es interesante la llamada a la funcin.
bre el valor aadido del 16%. Es decir, paga Ocurre en la lnea:
mos un 16% ms de lo que el producto cuesta
echo brutoANeto($_POST['numero']);
realmente.
Como argumento, transmito el valor del campo
Sin embargo, desde entonces ya no he cometido de entrada del formulario numero. La funcin
ms fallos en este tema. Es la oportunidad per torna el valor, calcula el resultado y lo devuelve
fecta para escribir una funcin que se encargue con echo.
de esta imporante conversin.
Validez de las variables en funciones
La funcin partir del valor bruto y calcular el Atencin: las variables que se declaran en una
valor neto, redondendolo dos decimales. (De funcin solamente son vlidas dentro de dicha
ello se encargar la funcin sprintf(), de la que funcin. As, la variable $zw es invisible para el
ya hablamos largo y tendido en el cuaderno an resto del script. Y lo mismo a la inversa: la fun
terior sobre PHP). Para terminar, la funcin de cin solamente puede acceder a los valores que
vuelve el valor modificado (convertido). se le transmiten como argumento.
function brutoANeto{$zw)
{ La funcin es una especie de contenedor ce
$zw = $zw / 1.16; rrado.
$zw = sprintf("%01.2f'', $zw);
return $zw; Las variables que utilizarnos fuera de la funcin
normalmente no sern visibles dentro de la fun
En el script, puedes guardar el resultado de la cin. Con una excepcin: con la palabra clave
funcin en una variable, o mostrarlo directamen global se convierte una variable en "variable glo
te con echo. Y eso mismo es precisamente lo que bal". Encontrars ms informacin en el manual
he hecho yo en el archivo del suplemento bruto oficial de PHP.
neto.php:
<h2>Convertir bruto a neto</h2>
<form action="<?php echo &
Ejercicios sobre funciones
$_SERVER("PHP_SELF"]; ?>" tJ
method="post"> A continuacin, te presento dos ejercicios sobre
<input t.ypeev t ext " nameevnume ro" funciones. En el ltimo ejemplo del cuaderno
<input type="submit" value=& aparecer una nueva funcin.
"Calcular">
</form> De neto a bruto
<?php Escribe una funcin propia que convierta el va
function brutoANeto($zw) lor neto en bruto. Llmala netoABruto. Inclyela
{ dentro de un documento de forma similar al
$zw = $zw / 1.16; ejemplo que hemos visto. Guarda el documento
$zw = sprintf("%01.2f'', $zw); como netobruto.php. Encontrars la solucin en el
return $zw;
archivo neiobruio.php,
echo brutoANeto($_POST['numero]);
Guardar una funcin de forma externa
?,
Guarda la funcin en un archivo externo y ll
malo function.inc.php. Vinclalo desde netobru
to.php. En este caso, no te dar la solucin.
18 lbum de fotos: carga de archivos

lbum de fotos: carga de archivos a


una pgina web
Qu te parecera un ejemplo de un calibre PHP recibe el archivo, lo comprueba y lo guar
mayor? Podrs cargar archivos a tu pgina da en la carpeta deseada.
web, directamente desde el navegador.

I Utilizaremos HTIP en lugar de FfP. Optimizado para grficos


El funcionamiento es sencillo: la idea es ofrecer He adaptado mi script a grficos, concretamen
a los usuarios un formulario HTML con un te a imgenes en formato GIF o )PEG. No se
campo de formulario especial para cargar ar puede utilizar con otros tipos de archivo. Tam
chivos: bin he decidido poner restricciones en cuanto
al tamao: no se permitirn archivos de ms de
200 kBytes (200.000 bytes).
Mi lbum de fotos en lnea Como ya hemos rucho, esta prueba se pro
C1rs1r 1rdth-o duce despus de que se cargue el archivo. Si
eW""-IGnc-Fiiij alguien pretende cargar un grfico de 1,5
megabytes, slo sabr que el archivo es de
masiado grande despus de esperar varios
minutos a que termine la carga.

Todas las imgenes se guardarn en una sub


carpeta llamada img. Y otro refinamiento: el
script mostrar en la propia pgina los grficos
acabados de cargar. Para ello, leer todos los
archivos de la carpeta y escribir las corres
pendientes etiquetas <img> en la pgina resul
tante.
Naturalmente, tienes carta blanca para modifi
car mi script para que acepte otros tipos de ar
chivo. Bastar con eliminar la consulta if co
rrespondiente, y sobre todo el mdulo de lec
Carga una imagen a tu pgina web. tura.

El usuario hace clic en Examinar y selecciona En la pgina siguiente presento el cdigo fuen
el archivo deseado desde su sistema Windows, te de carga.php, aunque por motivos de espacio
slo he copiado el rea comprendida entre
Linux o Mac. Al hacer clic en el botn Cargar
<body></body>.
archivo, el navegador carga el archivo en el
servidor web, y lo hace a travs de HTIP. No tengas miedo, analizaremos el cdigo paso
a paso. Por el camino aprenders varias fun
El proceso puede durar ms o menos en ciones nuevas que yo habr buscado y probado
funcin del tamao de archivo. Observa el previamente.
progreso en la barra de estado del navega Y hablando de funciones y bsquedas, ya has
dor. descargado la ltima versin del manual ofi
cial dePHP?
Una vez cargado el archivo, PHP se vuelve a
activar y comprobar que el archivo sea correc
to, pero esto se debe a la naturaleza del proce
so. PHP funciona sobre el servidor, no sobre el
cliente (cliente= tu PC).
lbum de fotos: carga de archivos 19
Consultar funciones en el manual de PHP Para la comprensin del cdigo fuente es muy
importante respetar la fantstica sintaxis
El manual de PHP constituye una fantstica PEAR, de la que tambin hablarnos en el cua
obra de consulta, sobre todo en lo que res derno anterior.
pecta a las funciones de PHP. Yo suelo traba Admira la belleza del cdigo siguiente, perfec
jar con este archivo de ayuda siempre abier tamente sangrado.
to. Si necesito una determinada funcin, me
dedico a hojear el manual hasta encontrar la
funcin adecuada o un script de muestra
que me pueda servir. Para ms informacin,
consulta el prrafo dedicado al manual en el
cuaderno anterior "PHP 5", o accede a
www.php.net/downls>ISl:d9GI php.

1 <hl>Mi lbum de fotos en linea</hl>


2 <h3>Cargar archivo</h3>
3 <form action='<?php echo $_SERVER['PHP_SELF1] ?>' method=11post"

4 enctype=nmultipart/form-data">
5 <input type=ttfile" name=11archivo">
6 <input type="submit" name='submit' value="Cargar archivo">
7 </form>
8 <?php
9 $ruta = "img/"; / / Indicar ruta
10
11 if (isset($_FILES['archivo']) && $_FILES['archivo') ['size'] > O) {
12 $tamanyomax = 200000; // Indicar tamao en bytes
13 $nombretemp = $ FILES l arch .vo t l [ 'tmp_name'];
t

14 $nombrearchivo = $_FILES[1archivo'] [1name1 ];


15 $tamanyoarchivo = $_FILES[1archivo1] ['size'];
16 $tipoarchivo = GetlmageSize($nombretemp);
17
18 if ($tipoarchivo[2] == 1 11 $tipoarchivo[2] == 2) { // GIF o JPG?
19 if ($tamanyoarchivo <= $tamanyomax) { // Archivo demasiado grande?
20 if (move_uploaded_file($nombretemp, $ruta . $nombrearchivo)) {
21 echo "<p>El archivo se ha cargado cbe-con xt coe yb s .
22 Tamao de archivo: <b>$tamanyoarchivo</b> bytes,
23 Nombre de imagen: <b>$nombrearchivo</b><br></P>";
24 else {
25 echo "<P>NO se ha podido cargar el archivo.</p>";
26
27 else
28 echo 11<p>El archivo tiene ms de <b>$tamanyomax bytes</b> y
29 es demasiado grande.</p>11 ;
30
31 else
32 echo "<p>No es un archivo GIF
33 o JPG vlido.</p>";
34
35 echo "e orm action='{$_SERVER['PHP_SELF']}' method='post1>
36 <input type='submit' value:'OK'></form>11;
37
38 $filehandle = opendir($ruta); // Abrir archivos
39 while ($file : readdir{$filehandle)) {
20 lbum de fotos: carga de archivos

40 if ($file!= ".11 && $file!=" .. ")


41 $tamanyo = GetimageSize {$ruta. $file);
42 echo "epec .mq src=' $ruta$file' $tamanyo [3] ><hr></p>\n11 ;
43
44
45 closedir($filehandle); // Fin lectura archivos
46 ?>

La array $_FILES contiene todas las propiedades


Formulario de carga del archivo cargado. En nuestro ejemplo, dentro
de $_FILES['archivo'] se encuentra el nombre del
Las lneas 37 no suponen ningn enigma. En archivo, el tamao del archivo, el MimeType
ellas creamos el formulario para cargar el archi (como image/ gif) y tambin, por ejemplo, el
vo. Lo importante es el par atributovalor adi nombre temporal del archivo.
cional enctype="multipart!formdata" de la etique
ta cform>. Slo gracias a ello se trata de un Despus de cargar el archivo, PHP Je asigna
"formulario de carga autorizado". un nombre temporal y lo almacena en una
El campo para cargar el archivo propiamente di carpeta temporal.
cho se genera mediante <input type=''file">. Au
tomticamente se crea un pequeo botn inteli
gente para seleccionar un archlvo. Por el contra Propiedades de $_FILES
rio, el segundo botn es el botn de envo de los
datos de la lnea 6. Cmo se puden leer estas propidades tan inte
resantes? Muy sencillo, agregando otra key a la
Puedes modificar el texto de los dos botones array:
mediante el atributo value.
$_FILES['archivo'][ 'propiedad' J
Ten en cuenta que he llamado archivo al "campo Tenemos a nuestra disposicin las siguientes
de carga": namee't archiuo", Este nombre de libre propiedades:
eleccin es importante, ya que deberemos respe Propiedad Explicacin
tarlo posteriormente en el script de PHP.
$_FILESarchivo']['name1 El nombre de archivo original
del archivo en tu ordenador.

La array $_FILES $_FILESarchivo1['type1 El Mime-Type del archivo,


p.ej. imagelgif para archivos
GIF o imagelpjpeg para archi-
A continuacin, veamos la consulta if que se ini- vos JPG. Dado que la propia-
cia en la lnea 11 y termina en la 37. En primer dad depende del navegador,
lugar, comprueba si existe un elemento de la es poco fiable y no muy rece-
array con la clave archivo (as es como se llama mendable.
el campo de nuestro formulario!). $_FILESarchivo1size') El tamano del archivo carga-
do en bytes.
La array $_FILES $ _FILES['archivo'J['tmp_name') El nombre temporal con el
que se guarda el archivo en el
Todos los datos cargados con H1TP y POST servidor.
(method="post") se almacenan en la array
$_FILESarchivoJ['error') El cdigo de error que se de-
$_FILES. Nuestro archivo del campo de for vuelve al cargar el archivo. O
mulario archivo se convierte en significa 'todo ck", 4 significa
$_FILES['archivo']. Se trata nuevamente de "no se ha cargado ningn ar-
chivo". Se introdujo en PHP
una array asociativa. Comprala con las ma 4.2, para ms informacin
trices $_POST, $_GET o $_REQUEST, de las consulta el manual de PHP.
que ya hemos hablado en la pgina 10. En rea
lidad es muy parecido. A nosotros nos interesan las siguientes tres pro
piedades:
$_FILES['archlvo']['trnp_name']
lbum de fotos: carga de archivos 21
$_RLES['archivo'J['name'] lndex 2 es un nmero en funcin del tipo de
$_FILES['archivo'J['size'] archivo de imagen
He renunciado a los cdigos de error, ya que los (1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF)
mtodos de comprobacin de que dispongo en lndex 3 contiene la cadena de caracteres co
mi caso son ms que suficientes. Y con esto vol rrecta en formato width="xxx" height="yyy"
vemos a la consulta if de la lnea 11. En la se El ltimo punto es especialmente interesante, ya
gunda condicin, con $_FILES['archivo'J['size'] > que podemos incluir esta cadena de caracteres
O, compruebo si realmente se ha cargado un ar directamente en la etiqueta mg.
chivo. Para ello, el tamao del archivo tiene que
ser mayor que O. Atencin a los grficos "saltarines"! Este es
un aviso para los webmasters que utilizan ba
Si algn insensato escribe un par de caracteres ses de datos inteligentes para presentar im
en el campo y pulsa el botn de carga, se crea genes cuyo contenido "salta" al cargarse en el
r un archivo, pero estar vaco. Esta medida navegador: este desagradable efecto se puede
nos proteger contra este tipo de situaciones. evitar! Slo tenis que familiarizaros con la
funcin GetlmageSize() y utilizar el ndice 3 de
Qu es lo que pasa en las lneas 1315? Aqu
la array. Yo lo he utilizado descaradamente en
transformo estas variables fijas en variables pro
la lnea 41 y 42, en la presentacin de los ar
pias, nicamente para que el cdigo sea ms f
chivos. Ms adelante volveremos sobre ello.
cil de leer y no me provoque confusin.
As, por ejemplo, transformo la complicada es Pasemos a la lnea 16. Aqu leo con GetlmageSi
tructura $_FILES['archivo'J['tmp_name'] en la va ze() todos los datos del nombre de archivo tem
riable $nombretemp, etc. poral del archivo ya cargado(!) y los almaceno
en la variable $tipoarchivo.
Determinar un tamao mximo
En la fila 12 he fijado un tamao mximo para el Archivo GIF o JPEG?
archivo. De este modo me aseguro de que ms Ahora se aclara la consulta if de la fila 18. El in
tarde no lleguen "peces demasiado gordos" a la dex 2 de la array $tipoarchivo me indica con tan
pgina. Tericamente, PHP acepta archivos de slo un nmero si se trata de un archivo GIF,
hasta 2 MB. JPEG, PNG o SWF. Y, dado que slo queremos
permitir archivos GIF o JPEG, por eso la consul
Sin embargo, las imgenes que se carguen ta tiene el aspecto que tiene.
desde mi formulario no podrn tener ms de
200 kBytes. (Por tanto, este es el punto que debers eliminar
si deseas permitir que se carguen otros tipos de
Por tu parte, puedes y debes ajustar este valor a archivo).
tus necesidades.
Se ha alcanzado el tamao mximo?
La consulta de la fila 19 comprueba si se ha al
Tipo y tamao de archivo canzado el tamao mximo de archivo permiti
do. Si el archivo es demasiado grande, se ejecuta
Qu ocurre en la lnea 16? Aqu entra en juego el else de las lneas 2730. De lo contrario, el
la funcin GetimageSize(). script contina en la lnea 20.
Se trata de una funcin extremadamente intere Y qu ocurre exactamente en la lnea 20?
sante, ya que reconoce los archivos GIF, JPG,
PNG o SWF y puede devolver su altura y an
chura. Adems, tambin devuelve el tipo de ar Funcin move_uploaded_file()
chivo, y precisamente necesitaremos esta pro
piedad ms adelante. Vamos a ocupamos de la funcin mo
ve_uploaded_file(). Se encarga de "trasladar", tal
El truco radica en que la funcin devuelve una como nos indica su nombre, el archivo II carga-
array, concretamente una matriz de 4 elementos. do" a otra ubicacin que deberemos definir co
lndex O corresponde a la anchura mo parmetro.
Index 1 corresponde a la altura
22 lbum de fotos: carga de archivos
El primer argumento de la funcin es el nombre nombre de archivo, tengo que guardarlo en una
de archivo temporal, el segundo la ruta de acce variable: $file= readdir($filehandle).
so y el nombre de archivo en la ubicacin final.
Sin embargo, por lo general una carpeta no suele
Aqu utilizaremos la ruta de acceso que ya contener un solo archivo. Para contarlos todos,
hemos definido en la lnea 9 en la variable recurro a un bucle. Necesitar un bucle que se
$ruta. En este ejemplo, movemos las imgenes mantenga activo hasta que readdiri) haya "recu
a la subcarpeta img y les asignamos el nombre perado" todos los nombres de archivo de la car
de archivo original. peta. Y de esto se ocupa precisamente mi queri
do bucle while, que he transformado en $file =
Ten en cuenta que, si se carga un archivo nue readdir($filehandle) (lnea 39) y que se cierra en la
vo cuyo nombre coincida con otro ya existen lnea 44.
te, el nuevo sobreescribir el antiguo.
Excluir los caracteres . y ..
Si la funcin tiene xito, presentaremos un par La primera vez que prob las funciones opendirt)
de datos sobre el archivo cargado. Esto ocurre en y readdir(), qued estupefacto. Mi fantstico echo
las lneas 2123. (ver lnea 42) no slo devolva los nombres de
archivo, sino tambin unos curiosos puntos; po
da ser un punto solo o dos.
Un punto indica la carpeta actual, y dos pun-
Todo ha funcionado, ahora hay que hacer clic en OK.
tos indican que se trata de una carpeta de ni-
Al hacer clic en el botn OK (formulario de las vel superior en la jerarqua. Ambos caracteres
lneas 3536), desaparece el mensaje de confir se incluyen de forma totalmente automtica.
macin. Tambin se vaca la memoria cach del
navegador, ya que de lo contrario el usuario po Con que esas tenemos ... ningn problema, slo
dra volver a cargar el archivo al servidor. tenemos que filtrar estos caracteres en la lnea 40
y listos. La lnea 42 vncula mis imgenes en la
etiqueta <img> y coloca cada imagen en un p
Lectura de un directorio rrafo propio.
Hasta aqu hemos llegado, y ahora ya sabes c La fila 41 lee, con ayuda de la funcin Getlmage
mo cargar archivos a un servidor y cmo com Size() de la que ya hemos hablado antes, el ta
probar que todo ha funcionado. mao del archivo, para poder evitar el efecto de
los grficos "saltarines". Sorprendido?
opendir()
Por pura diversin, he aadido un "mdulo de
lectura" al script, que se encuentra en las lneas Autorizar la carpeta
3845. Obsrvalo con atencin: qu ocurre en la
lnea 38? La funcin opendiri) se limita a abrir Ha llegado la hora de publicar el script en el ser
una carpeta, y devuelve un "handle", una espe vidor y comprobar si todo funciona como debe
cie de apuntador. ra. Y a la hora de la verdad ... los posibles men
sajes de error dependern de tu proveedor.
En nuestro ejemplo, opendiri) abre la carpeta
$ruta, es decir, el subdirectorio img.

A continuacin, almaceno este indicador de di Mi lbum de fotos en lnea


rectorio en la variable $filehandle (aunque podra
haberla llamado de cualquier otra forma).
,. lls-----1
readdir() Wani9e:-_....,.s.,,t_._..,_MG_6179,W-Wtd opa ._p..,.._
A continuacin, se ejecuta la siguiente funcin, dmod...._,11,u , ..... .. -27

la funcin readdir(). Esta funcin lee los nombres ..--..JIIO.Ullilk .. -


de archivo del directorio y los devuelve. Para ._.,_M0_6J1t.S...._...... e r = ---
ello solamente necesita el handle del archivo: "
readdir($fi/el,andle). Y si slo quiero utilizar el
lbum de fotos: carga de archivos 23
En mi caso, la funcin move_uploadedJile() ha fa
llado. Por qu? Sencillo: porque todava no
Ejercicios: propuestas para
haba asignado derechos de escritura a la carpeta
img. mejoras
Utiliza tu cliente FTP para acceder a dicha carpe A pesar de lo completo que es el script, siempre
ta y asignarle un CHMOD 777, es decir, permitir hay algo que se puede mejorar. As que aprove
la lectura, la escritura y la ejecucin. Los princi charemos esta oportunidad para practicar con
pales programas FTP pueden hacerlo, incluso un par de ejercicios.
WS_FTP Limited Edition incorpora esta funcin.
Al hacerlo, asegrate de aplicar el comando Encontrars los resultados a los ejercicios en el
CHMOD a la carpeta deseada. Haz clic en el pa suplemento del cuaderno, pero atencin: no vale
nel derecho con el botn derecho del ratn en el hacer trampas. De lo que se trata es de que
nombre de la carpeta. aprendas probando. Creme, la experiencia y los
contratiempos te ayudarn a avanzar.
Selecciona el comando chmod (UNIX). Apare
cer la ventana REMOTE FILE PERMISSIONS. Ac Ejercicio 1: anchura mxima
tiva todas las opciones (3x3 casillas en READ/ Quizs no te parezca tan importante el tamao
WRITE/EXECUTE) y haz clic en OK. La carpeta mximo y prefieras mostrar en su lugar la anchu
tendr plenos permisos, y en segundo plano ra mxima del archivo.
se ejecutar el comando chmod 777. En el fondo, tiene sentido: las imgenes dema
siado anchas podran afectar el diseo de la p
gina. Haz lo siguiente:
Domainfactory o ms Sustituye la consulta sobre el tamao en una
consulta sobre la anchura. La imagen que se
problemas con chmod cargue no podr tener ms de 600 pxeles.
Ajusta las variables en consecuencia.
En la primera edicin de "Introduccin a PHP"
publicada en Espaa en 2002 pas por alto to
talmente la cuestin de los permisos de carpetas. Mi ilbUJDJ de fillltos en .lneai
Como cliente de la empresa alemana de hosting
l&l no tuve que preocuparme de eso, ya que
mis ejemplos funcionaban sin chmod. As, no me
di cuenta de que el ejemplo del libro de visitas y
--1- n ...... '*"i!
Bain.w.r:--b,u1.,mmttlf'IU11rsdltiml!Wi.aa..
'

la encuesta no funcionaban en otros proveedo


res. Sin embargo, esta vez no dejaremos este te
ma pendiente. Muestra un mensaje de error descriptivo para
Para que no me volviera a ocurrir algo as, lo el usuario.
que hice fue registrarme con varios proveedores Consejo: slo tienes que cambiar ligeramente el
que ofreciesen PHP. Volvamos al script que nos script, ya que las variables correspondientes ya
oscupa: la empresa alemana de hosting Do estn preparadas. Para comprobar la anchura
mainfactory (www.domalnfactory.de) me provoc utiliza la funcin getlmageSize() y su valor ndice
otro problema. La carga de archivos funcionaba, O. Encontrars mi solucin en el archivo car
pero las imgenes no se mostraban. La solucin gaancho.php.
es agregar el siguiente cdigo entre la lnea 20 y
21: Ejercicio 2: guardar el archivo de imagen
chmod($ruta $nombrearchivo, 0666);
con otro nombre
Otro posible problema del script es que, cuando
El motivo es que el servidor de Domainfactory se cargan archivos con el mismo nombre, el ar
est configurado de forma que, tras su carga, los chivo nuevo sustituye al anterior. No sera me
archivos no tienen todava permiso de lectura. jor asignar a cada archivo un nombre nuevo?
Como se puede ver, la experiencia es lo que Tu tarea: completa el script de forma que se
cuenta al final, y uno se puede topar con pro asigne a cada archivo un nombre rnicor que cam-
blemas en cualquier punto del proceso. bie a cada segundo.
24 lbum de fotos: carga de archivos
Consejo: tendrs que ampliar el segundo argu Ejercicio 3: proteccin con contrasea Por
metno de la funcin move_uploaded_file() de la l desgracia, nuestro script todava tiene un
nea 20. Y otro consejo ms: hay una funcin que pequeo problema esttico. Cualquiera puede
devuelve la cantidad de segundos transcurridos cargar archivos, sin ms. Establece una protec
desde el 1 de enero de 1970. Ampla el nombre
cin mediante contrasea. Para ello, agrega un
de archivo utilizando este valor. De acuerdo?
campo adicional que pida la contrasea. Slo las
Encontrars mi resultado en el archivo tiempo personas que conozcan la contrasea podrn
carga.php. Espero haberte dado suficientes pistas. cargar un archivo.
El archivo se ha cargado coa xito. Tambin puedes proteger toda la carpeta utili
Tamao de archivo: 177982 bytes, Anchura: 427 zando htaccess. En muchos proveedores de hos
ting, se puede hacer fcilmente desde el men
Nombre de imagen: 1145815959_MG_:6182.jpg de configuracin del panel de control.
Ajusta tambin la [orma en que se muestra el
nombre de archivo .
Interfaz grfica phpMyAdmin 25

Comodidad para MySQL - La inteaz


grfica phpMyAdmin
A partir de este punto empezaremos a tratar En pocas palabras: MySQL y phpMyAdmin
MySQL, el prctico programa de bases de datos son el "dreamteam" para el manejo de bases
de origen sueco. MySQL es potente, rpido y de datos. En mi opinin, se trata de una com
fiable y es capaz de manejar con soltura grandes binacin con tanto potencial que la prefiero a
cantidades de datos. Access y cia., y la utilizo desde hace tiempo
Aunque, corno era de esperar, siempre hay un para administrar mis datos profesionales.
"pero": el programa se controla mediante la l
nea de comandos, es decir, escribiendo directa Pero aqu no se acaba todo, sino que, adems,
mente los comandos en una ventana. XAMPP instala automticamente la ltima ver
sin de phpMyAdmin. Para acceder a
Sera mucho ms agradable utilizar para ello phpMyAdmin, escribe lo siguiente en la ventana
una interfaz grfica, corno la de Access y otros del navegador:
programas. Y precisamente este hueco es el que
http://localhost/phpmyadmin
llena phpMyAdmin.
Como recordatorio: el nombre de usuario es root,
phpMyAdmin es la interfaz de MySQL basa la contrasea se puede dejar en blanco.
da en PHP y HTML. Gracias a phpMyAdmin Sin duda, si tu proveedor de hosting ofrece
es posible crear, editar y eliminar bases de da mySQL tambin utilizar este prctico progra
tos y tablas. phpMyAdmin se utiliza a travs ma. Perrnteme que lo repita una vez ms, ya
del navegador. que es un punto muy importante: un buen pro
veedor te permitir acceder a tus bases de datos
en MySQL a travs de phpMyAdmin.

Bienvenido a phpNyAdmin 2.7.0pl1


:S.0.11\ eftCTtfffHO ----

.. _ ........
_
e'""

:...-::=---- ..
j I <.. ...tf') "'
.
1
110... llll:=;
11!Jf l
.... *'"'"- -
-,l."""9Ql.<lffl'4U."""-

, ,-.. _.,
-9 _i jJ


111 ...... .
-- -

.

l ...._ ...... _ iil

. . .... .._
i m
-.-t.z:.io-,
- "'9QI. . ................
tJ fe'W\11 ,i.-.1
.,.._

.. .
. . _ . . . . ., .............. .. . _ .-
_ ., . . . . . . " "9 Ql.. . .

..

_ _
. _.... . . . , -
"" '5 'Q I .

........._..
phpMyAdmin, la interfaz grfica para MySQL
26 Interfaz grfica phpMyAdmin
Una vez creada la base de datos, slo necesita
phpMyAdmin en los distintos remos el nombre del host (hostname) y el nom
bre de usuario y la contrasea que hayamos de
proveedores finido.

Cmo se puede acceder a phpMyAdmin? Me Atencin: en dreamhost no se utiliza "local


resulta muy difcil poner ejemplos de proveedo host" como hemos venido viendo hasta ahora,
res espaoles, ya que principalmente conozco sino un nombre de host de libre eleccin vin
los de la esfera alemana. culado al nombre de dominio.
Sin embargo, te presentar a modo de ejemplo el
funcionamiento de un proveedor de Estados As, si creo una base de datos llamada base, en
Unidos, Dreamhost (www.dreamhost.com), que a un hostname llamado lwst.midominio.com con un
mi parecer tiene una muy buena oferta de servi usuario pepe y una contrasea botella, para acce
cios por un precio inmejorable. der a phpMyAdmin slo tendr que escribir:
Los servidores de Dreamhost se encuentran en host.midomino.rom
Los Angeles, y su servicio es amigable y de res Y se abrir una ventana emergente para introdu
puesta rpida. Adems, su sistema de ayuda ha cir el nombre de usuario y la contrasea y acce
pasado a ser un wiki colaborativo, y tambin der a phpMyAdmin. Es decir, el usuario y la
mantienen un blog en el que explican las ltimas contrasea de mySQL son los mismos para
noticias internas de la empresa: phpMyAdmin.
blog.dreamhost.com.
Recientemente, en Dreamhost han simplificado
En cualquier caso, no te conformes con mis ex el procedimiento de administracin y acceso a
plicaciones. En la pgina www.buscahost.com en bases de datos, de modo que es posible asignar
contrars informacin sobre los principales pro mltiples bases de datos a un solo hostname. La
veedores de hosting de Espaa. ventaja es que es posible acceder a todas las ba
ses de datos con el mismo nombre de host
Un ejemplo: Dreamhost mysql, y utilizando siempre la misma URL de
En el caso de Dreamhost, para comprender me acceso a phpMyAdmin.
jor como funciona, te mostrar el aspecto del
formulario del panel de control de Dreamhost Creacin de subdominios
para la creacin de una base de datos:
pteasc choose the k111d of hosnn you would hke lo add:
MYS L
fuly Hosted cu....., 10"' lk ...... ..,. ....... _,. ...... ,..1

Wfllbmt --..
OonMlnlollo,t:
PHP v-io..: 1 i.1.2 0 4.4,2
iJ
0.u.lM M-c'i--=--,, &tr

-r
tfMIIWHIIII: mytql dQlollllt(Ofl1 ,, "!MM, lf 4oW, ,,Mo 0M
O FutOOI Suol>o<1:?


1.nt,,""'" Cr ..,
'Mw W-.1
fin! UMr:
jPnl'l!'Ol'd
do Alle lM - lti .,_, Ull?
Oitt.Jb.Jn Comment. Both tmp//www.domMl.com/ and ht:/ldoma1tt.oom/ wOf\c.
0Add -" !f 50IMbody DON to http:J/flotNfl,CMI/
O www. lf .-.oocty gou to http lt-w.dotrYA-,V
f1.F..l.l.ly..""91 ....d, ...,. .. ....._,,..,

En este formulario deberemos indicar tres datos Cllllffle i


fundamentales:
Crear un subdominio en Dreamhost es tan
Un nombre para la base de datos (Database sencillo como crear un dominio. Basta con
narne)
elegir "Add New Domain /SubDomain" en el
Un nombre de host (Hostname, el equivalen panel de control. Escribe el nombre del domi
te a localhost en nuestro servidor local) que nio sin www (!). Una vez creado el subdomi
estar compuesto por un nombre de libre
nio, en la pgina de gestin MySQL el sub
eleccin seguido de un punto y el nombre de
dominio aparecer automticamente en la lis
dominio, por ejemplo
nombrehost.dominio.com ta para crear una nueva base de datos
MySQL.
Un usuario (Usemarne) y una contrasea
(Password) para acceder a la base de datos.
Interfaz grfica phpMyAdmin 27

Gracias a la flexibilidad que ofrece, es muy sen


cillo utilizar Dreamhost como "banco de prue
bas". Basta con crear un subdominio para hacer
pruebas y probar en l tus scripts de PHP
/MySQL. Cuando todo funcione a la per
feccin, bastar con trasladarlos al dominio
principal.

Otras opciones
Repito que todas estas explicaciones pueden va
riar de un proveedor a otro. Hay proveedores
que permiten utilizar el mismo nombre de usua
rio y contrasea para los servicios de FTP,
mySQL y phpMyAdmin, mientras que otros
obligan a usar distintas claves de acceso.
Adems, cada proveedor tiene su propio panel
de control, organizado de distinta forma, y todos
tienen sus particularidades de funcionamiento.
Par salir de dudas, lo mejor es que consultes a tu
proveedor (seguramente ofrecer algn tipo de
pgina de ayuda).

Hosting PHP/MySQL gratis?


S, tambin existe, por ejemplo en:
www.tripod.Jycos.es o
www.metropoligJobaJ,rom. Sin embargo, slo
es recomendable utilizar estas ofertas "con
publicidad" en caso de extrema necesidad.
28 Bases de datos y tablas

Bases de datos y tablas: una libreta de


direcciones
Ha llegado el momento de lanzarse a phpMy Debajo del nombre de la base de datos en la lis
Adrnin. Te mostrar las principales fun- ciones ta desplegable del marco izquierdo se muestra
basndome en una libreta de direcciones, una el mensaje No se han encontrado tablas en la base
alternativa fantstica a la pesada y farrago sa de datos.
libreta de direcciones de Outlook.
Ninguna tabla? Efectivamente, la base de
Inicia la variante offline de phpMyAdrnin datos es un simple "contenedor". Por eso en
desde http://localhosUphpmyadmln. realidad no importa el nombre de la base de
datos. Los datos propiamente dichos se al
macenan en tablas de la base de datos.
Una nueva base de datos
Eres un profesional de SQL? Seguro que toda Una tabla para categoras
va no, pero pronto lo sers. Preparndonos pa
ra ese futuro, llamaremos a nuestra primera ba Est visto que necesitamos tablas. Para nuestra
se de datos sql pofi. Este ejemplo funcionar libreta de direcciones, he pensado en crear dos.
como mnimo offline, ya que algunos provee Una de ellas contendr las direcciones con n
dores de hosting no permiten que los usuarios meros de telfono, direccin de email y dems,
creen sus propias bases de datos. y la llamaremos:
Si deseas asignar otro nombre a la base de da direcciones
tos, no hay ningn problema. Sin embargo, pro
La segunda tabla almacenar las categoras, por
cura no utilizar espacios en blanco ni caracteres
especiales, incluidos acentos y diresis. lo que se llamar:

As se puede crear una base de datos: categoras


De este modo podrs ordenar tus direcciones en
cajones corno Privado, Amigos, Parientes,
Pesados, y lo que se te ocurra, de forma similar
a como lo haramos en Outlook o cualquier otro
programa de administracin de direcciones.
1. Haz clic en el campo Crear nueva base de da Empecemos por el principio, con la tabla de ca
tos. tegoras. En esta ocasin, la crearemos a mano.
2. Escribe sql _prof i. Admito que, a primera vista, crear tablas con
3. Haz clic en el botn Crear. phpMyAdrnin es mucho ms sencillo. Basta
con escribir el nombre de la tabla en el cam
po adecuado, indicar la cantidad de campos
llffl>
'
..
D.. :E!. :!r y hacer clic en Aceptar. De acuerdo. Pero en
esta ocasin intentaremos no hacerlo al fin y

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


i,. . d.....
t,,,.

- al cabo, de lo que se trata en este cuaderno es


de aprender SQL. Y, si quieres consultar con
xito tu base de datos MySQL con PHP, lo
4. La base de datos ya est creada y aparece
mnimo es comprender y dominar los distin
enseguida en el men desplegable del mar
co izquierdo de la ventana. tos comandos.
Adems, PhpMyAdrnin te mostrar el coman A continuacin, te presentar tu primer coman
do SQL que ha ejecutado en realidad. En nues do SQL escrito a mano. Fjate en la sintaxis.
tro caso, el comando es: CREATE DATABASE
sql_profi.
Bases de datos y tablas 29
Crear una tabla: CREATE TABLE Por su lado, hemos asignado al campo categora
El comando para crear una tabla no poda ser el tipo de dato VARCHAR. Este tipo de dato puede
ms sencillo: almacenar cadenas de caracteres de longitud
variable, hasta 255 caracteres. Por tanto, con
CREATE TABLE nombretabla ()
VARCHAR 12 s: fijo una longitud mxima de 25
El nombre de la tabla vuelve a ser de libre elec caracteres.
cin, al igual que ocurra con el nombre de la
Existen muchos otros tipos de datos, por ejem
base de datos (y con las mismas limitaciones).
plo TEXT para guardar textos de hasta 65.535
Por tanto, nuestra tabla se llamar:
carcteres, o SMALLINT para la misma cantidad
CREATE TABLE categorias () de nmeros.
(sin acento). Los comandos SQL se suelen escri Un par de pginas ms adelante nos ocupare
bir en maysculas para facilitar su legibilidad. mos de los principales tipos de datos.
Pero el comando todava no est completo. Fal
ta la definicin de los campos, concretamente NOT NULL y AUTO_INCREMENT
entre los dos parntesis. Volvamos al id. El campo NOT NULL signfca
Campos? Ftbol? No, en realidad me refiero a que el valor no puede ser O. Por tanto, el re
los campos de la tabla de la base de datos. Para cuento de categoras debe empezar en l. Con
las categoras tengo pensados dos campos. AUTO_lNCREMENT indico que el nmero se
incrementar automticamente, es decir, au
Dos campos para una tabla mentar en 1 cada vez. Si deseas fijar por ti
mismo el orden, puedes eliminar este atributo.
Uno de los campos de la tabla ser el id, es de
cir, el nmero de identificacin. A cada catego
ra le corresponde un nmero nico. El campo clave
Al segundo campo lo llamaremos simple y Ila
namente Categora, y lo reservaremos para la El comando principal, sin embargo, es PRIMA
denominacin real de cada categora. RY KEY. Nuestro campo id se convierte en
campo clave, en la clave primara. Qu sgnf
Los nombres de campo descriptivios contri ca eso?
buyen a mantener la visin de conjunto.
Aqu s se pueden usar acentos. Claves primarias
La clave primara es una forma de referirse a
Definiciones de campos una cadena de caracteres de forma unvoca.
Tambin tengo preparadas las definiciones de A cada campo se le asigna un valor disstinto.
cada campo: En el ejemplo, cada campo tendr un nmero
distinto. Gracias a la instruccin AUI'O_IN
Nombre del Definicin
campo CREMENT no tengo que preocuparme de
Id INT NOT NULL AUTO_JNCREMENT asignar la numeracin manualmente. La cla
PRIMARY KEY ve primaria no tiene que ser un nmero,
Categorla VARCHAR(25) , tambin se permiten palabras o cadenas de
caracteres.
Veamos en primer lugar la definicin ms com
plicada. Qu son todas esas palabras en ingls
que he puesto junto a id? Introducir un comando SQL
Tipos de datos de campos Hasta aqu la teora, y ahora volvamos a la in
Ante todo, definamos el tipo de dato del cam terfaz de phpMyAdrnin. Vamos a crear la tabla
po. El campo id es del tipo INT (de Integer). Es de una vez. Haz clic en la opcin SQL, introdu
decir, es un nmero entero. ce el comando y haz clic en OK.

El tipo de dato INT acepta valores entre


2100 y +2100 millones. Tericamente, podras
guardar ms de 4000 millones de categoras
en tu tabla.
30 Bases de datos y tablas
i9 S.,,..,do" llu>tU @! 9,... .S. t:os. l_ptof!
di' J,9QI. t,a..- fr'lc....-, ... .t.\e,.._.._ Si todo funciona como debera, deberas estar
" u-- viendo un mensaje de confirmacin. De lo con
Su c:onsulta et con ,tll,o (LA o:,neulta tllrd4 O.O'!'t3 Ml9) trario, tendrs que buscar algn error en el co
amsutta,SQL:
CREA.TI, lM!L6 Ql
mando. Por ejemplo, comprueba que cada lnea
kl

#OfH\11.LNJlO_IH(REt.tEIHKE'I'
J
entre parntesis termine con una coma, a ex-
cepcin de la ltima lnea del comando.

El comando SQL se ha ejecutado con xito.

CREATE TABLE categorias (


id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Categoria VARCHAR(25)
1

Introduccin de datos o / X i Privado

o / X 2 Amigos

o / X 3 Pantl!cll

o / X 4 Compa d tnibaj(I

t. Marci,r todo&// Dumarar todo, Pilra los qiM

[ Mostrar 1 1 ] fllas emzando de O

Espero que todo haya funcionado a la perfec en modo\ horti:,:uital [ y rer los ene.

cin. A pesar de haber creado la tabla, sta si VI.U de 1mJXU1n 'l. Prevk&ua1fz.8c:il'I
gue estando vaca, pero pronto le pondremos
remedio. Introduce un par de datos, esta vez, t!'lil'(.(tardar e.is;ta ,;:onsutta en favaritos---------

utilizando directamente phpMyAdmin: Et;quebi:

l. Asegrate de haber seleccionado la tabla.


Para ello, haz clic en el nombre de la tabla Desde aqu tambin tienes la opcin de introducir
en el marco izquierdo de la ventana. nuevos datos, seleccionando Insertar nueva 'fila
2. En el men de pestaas de la parte superior
de la ventana, haz clic en la ficha Insertar. Tabla de direcciones
3. Escribe el primer nombre de categora, por
ejemplo Privado. Nuestra segunda tarea pendiente es la creacin
de la tabla de direcciones. Analizando el co
Si has seleccionado AUTO_INCREMENT, no mando SQL podrs deducir los campos que te
tendrs que escribir a mano el id. En ese ca propongo para la tabla.
so, se crear automticamente por ti. CREATE TABLE direcciones {
id INT NOT NULL AUTO_INCREMENT cP
4. Rellena varias categoras ms, por ejemplo PRIMARY KEY,
Amigos, Parientes, Compaeros de trabajo. Tratamiento VARCHAR(lO),
Nombre VARCHAR(25),
Inserta nuevas categoras a tu gusto. Apellido VARCHAR(25),
Calle VARCHAR(25),
Mostrar la tabla CP VARCHAR ( 5) ,
Si tienes curiosidad por ver el aspecto que tiene Localidad VARCHAR(30),
tu tabla, haz clic en la ficha Examinar. Desde Tel VARCHAR(25),
aqu podrs visualizar, eliminar, editar e incluso Mvil VARCHAR(25),
ordenar los datos de la tabla. Si, por el contra Mail VARCHAR(35),
rio, lo que queires es introducir ms datos, se Website VARCHAR(35),
Categora INT,
lecciona Insertar.
Notas TEXT
Bases de datos y tablas 31

Tambin aqu tenemos un campo clave, pero es


ta vez no debes olvidarte de
AUTO_INCREMENT. Le siguen los campos
habituales de cualquier base de datos de direc
ciones: el Tratamiento, que distingue el sexo de
la persona, y donde podemos indicar Sr o Sra.
Los dems campos no tienen ninguna particu
laridad. En el campo Categora slo tienes que
introducir el nmero de la categora que desees
asignar. Es decir, debers introducir el id de la
tabla categoras.

Por lo general suele resultar muy prctico


dividir datos entre varias tablas. La introduc
cin directa de las categoras podra estar su
jeta a errores, ya que cualquier error de orto
grafa (Padiente, Parriente) provocara que se
tratase de dos categoras diferentes.

Gracias a que es del tipo TEXT, el campo Notas


puede aceptar hasta 65.535 caracteres. De esta
forma, podrs aadir notas muy largas sobre
cada uno de tus contactos.

Introduccin de datos
Tu siguiente tarea es sencilla: rellenar la base de
datos de direcciones. Escribe los datos de algu
nos de tus amigos, conocidos y parientes. Para
empezar puedes utilizar phpMyAdmn, de la
parte difcil nos encargaremos ms tarde.

32 Tipos de datos de MySQL

Principales tipos de datos de MySQL


Ha llegado el momento de presentar los prin Sin embargo, si llegarnos a tener varios miles de
cipales tipos de datos de MySQL. Recuerda: cadenas de caracteres, un par de bytes ms o me
nos pueden jugar un papel muy importante. Pero
Selecciona el tipo de datos que ocupe el m no hay que preocuparse, no se necesitan todos los
nimo espacio posible. tipos de datos. Mis "favoritos" son INT,
VARCHAR, DATE y TEXT. Para todo el cuaderno,
En las tablas pequeas este tema seguramente con estos cuatro tendremos ms que suficiente.
no supondr ningn problema.

Tipo de dato Descripcin Propiedades Espacio


Cadena de caracteres de longitud Acepta entre 1 y 255 caracteres, la longitud Longitud del valor ms
IVARCHAR(M)
j variable mxima se se determina mediante M, es obliga-
torio especificar (M)
1 Byte

Cadena de caracteres de longitud Acepta entre 1 y 255 caracteres, la longitud M Bytes


CHAR(M) fija mxima se se determina mediante M, es obliga-
1 torio especificar (M)
Cadena de caracteres con un No tiene en cuenta maysculas y minsculas Longitud del valor ms
rTEXT jximo de 65.535 caracteres (64 rmportante para ordenar y comparar) 2 Bytes
lKB)

S tiene en cuenta maysculas y minsculas (im-


Cadena de caracteres con un Longitud del valor ms
BLOB

MEOIUMTEXT Cadena de caracteres con un iene en cuenta maysculas

'
y minsculas

Longitud del valor ms

mximo de 65.535 caracteres (64 portante para ordenar y comparar) - adecuado 2 Bytes
KB) tambin
t para datos binarios
mximo de 16.777.215 caracteres (importante para ordenar y comparar) 3 Bytes
(16 MB)

MEOIUMBLOB Cadena de caracteres con un Sl tiene en cuenta maysculas y minsculas (im- Longitud del valor ms
mximo de 16.777.215 caracteres <>rtante para ordenar y comparar) - adecuado 3 Bytes
L (16 MB) f..mbin para datos binarios

!1NT o tambin Nmero entero entre 2147 millo- El atributo adicional UNSIGNED lo limita avalo- 4 Bytes (32 Bits)
INT(M) lnes y 2147 millones, (M) es cpclo- res positivos. INT UNSIGNED acepta valores en-

I SMALLINT o
f-------+--
nal
--- ---,
tre O y 4300 millones

Nmero entero entre -32.768 yJSi se utiliza el atributo adicional UNSIGNED,


------ -----1
2 Bytes (16 Bits)
tambin .J32. 767, (M) es opcional acepta un rango de valores de entre O y 65.535
SMALLINT(M)

TINYlNT o tam- Nmero entero muy pequeo entre Si se utiliza el atributo adicional UNSIGNED, 1 Byte
itnYINT(M) =127. (M) es opcional lacep un rango de valores de entre o y 255
1

FLOAT Nmero de coma flotante con En otras palabras: un nmero con coma con una 4 Bytes (32 Bits)
rango de valores de entre gran precisin detrs de la coma (recuerda que,
+/-1, 175494351 E-38 y al introducirlo en la base de datos, en lugar de
+/-3,402823466E+38 coma debers utilizar el punto decimal)
t-- -- --
DOUBLE Nmero de coma flotante con un Un nmero decimal con una gran precisin de- 8 Bytes (64 Bits)
rango de valores de entre tras de la coma (Double Precision)
+/- 2.2250738585072014E-308 y
+/- 1.7976931348623157E+308 1
DATE -Campo para almacenar la fecha en Comprueba si se han utilizado menos de 32 dias 3 Bytes (24 Bits)
formato 31') L31.12.ssss
YYYY-
MM-DD
('2004-
12- y 13
meses,
rango de
valores
entre
01.01.100
0y I
Tipos de datos de MySQL 33
DATETIME

0
TIMESTAMP o
Campo para almacenar la fecha y
la hora en formato YYYY-MM-DD
hh:mm:ss ('20041231 23:58:58')
Fecha y hora actuales en formato
YYYYMMDDhhmmss, sirve desde
Tambin determina la hora, rango de valores en-
tre 01.01.1000 y 31.12.9999
a Bytes (64 Bits)
Se puede controlar mediante M, M puede aceptar.a Bytes (32 Bits)
por ejemplo los valores 14, 12, 8 o 6, en
l
TIMESTAMP(M)
19700101000000 hasta el ao T1ME- STAMP(12} la fecha slo tiene dos
2037 cifras YYMMDDhhmmss, en TIMESTAMP 8 la
fecha tiene cuatro cifras, pero se pierde la
hora ...


34 Introduccin, actualizacin y eliminacin de datos

Introduccin, actualizacin y
eliminacin de datos
Volvamos a nuestra tabla de direcciones. Ya has Encontrars el cdigo fuente ms abajo en esta
introducido algunas direcciones con ayuda de misma pgina. Prubalo. Selecciona el rea SQL
phpMyAdmin? Se acabaron las comodidades, y escribe el comando a mano:
ha llegado la hora de dedicarse a SQL. o.10 ..
h,.,..,..,_ IOln"'

t -
-'t.,,..,._ - !MaS-..,
Introduccin de datos:
INSERT INTO ' -
? . .
Para introducir datos, utilizaremos el comando
INSERT INTO. La sintaxis es la siguiente:
-= -.----.a .......,_

INSERT INTO tabla () VALUES () ""' ......... - - w ..-.,....,.1]11

Naturalmente, deberemos sutituir tabla por el


nombre de la tabla de la base de datos, en nues -
tro caso, direcciones.


" ""
(J._..,. ..,.o1,. ..,,_.,_
o-- ..------
- ,-.., ., --

Entre el primer par de parntesis deberemos in


dicar los nombres de campo de la tabla que se de
seen tener en cuenta. En nuestro caso, todos Excepcionalmente, ha funcionado a la primera: cuan
menos el id que se asigna automticamente. Entre do se utilizan comandos tan complicados no siempre
los segundos parntesis escribiremos los valores es as.
de dichos campos. Ten en cuenta que:
Existe tambin una forma abreviada de
La asignacin y el orden deben coincidir to
talmente. INSERT INTO, en la que se omite el primer
par de parntesis. En ese caso, en el par de pa
Cada valor se debe indicar entre comillas
simples. rntesis detrs de VALUES se deben indicar
los valores de todos los campos, y hacerlo en
Todos los pares de comillas simples se sepa
el orden correcto. En nuestro caso, debera
ran mediante comas.
mos incluir un par de comillas (") vaco para
El ms mnimo error puede provocar un
mensaje de error en phpMyAdmin. el campo id.

INSERT INTO direcciones


(Tratamiento, Nombre, Apellido, Calle, CP,,Localidad, Tel, Mvil, Mail, Website, &
Categora, Notas)
VALUES
('Sra.', 'Clara, 'Martinez', 'Calle de la pera, 12', '08080', 'Barcelona', c9
'93-1234567', '636-123456', 'claras@mimartinez.es', 'l', '')

Actualizacin de datos: Slo tienes que conocer el id de la cadena de


caracteres u otro valor nico.
UPDATE Si Clara Martnez tiene el id 3 y queremos modi
Si te interesa actualizar un campo, no hay pro ficar su direccin, bastar con escribir:
blema. No importa si se trata de un solo campo UPDATE direcciones SET Calles'Calle de la
o de todos los de la tabla. Escribe UPDATE tabla pera, 8' WHERE id=3
SET ...
Introduccin, actualizacin y eliminacin de datos 35

Aqu aparece por primera vez la clusula


WHERE.

Tambin es posible modificar la calle y el telfo


no, separando los datos mediante una coma:
UPDATE direcciones SET Calle='Calle de la
pera 8', Tel='93-8938721' WHERE id=3

Eliminacin de datos:
DELETE
En la instruccin para eliminar datos de la tabla
tambin es necesario utilizar la clusula WHE
RE. El siguiente comando eliminara la cadena
de caracteres nmero 3:
DELETE FROM direcciones WHERE id=3

Y para eliminar toda la tabla de direcciones del


disco duro, slo hay que escribir:
DROP TABLE direcciones
36 Mostrar, filtrar, ordenar y vincular datos

Mostrar, filtrar, ordenar y vincular datos


Seguro que no slo quieres introducir y editar Si, por el contrario, quieres mostrar el apellido y
datos, tambin te interesar mostrarlos. Pues el nombre, sepralos mediante una coma:
precisamente de eso nos ocuparemos ahora.
SELECT Apellido, Nombre FROM direcciones
En este captulo, veremos cmo podemos selec
cionar datos; naturalmente, con la instruccin
SELECT. No en vano SELECT significa SELEC Filtrado con WHERE
CIONAR.
Y si mostrsemos solamente los contactos de
Barcelona? O los que viven en una determinada
Mostrar todos los datos calle? Para ello utilizaremos la segunda palabra
clave, WHERE, detrs de la cual se indican los
Si deseas mostrar una seleccin completa de to nombres de los campos de "forma comparati va",
das las filas de datos, debers utilizar el asterisco por ejemplo Loca L.dade ' Ba rce Lona ". Este sera
. El asterisco se utiliza como comodn para to el aspecto completo de la clusula WHERE:
do. WHERE Localidadz'Barcelona'
Detrs del asterisco, escribiremos FROM y des El comando completo sera:
pus indicaremos el nombre de la tabla.
SELECT * FROM direcciones WHBRB
Localidad'Barcelona'
No olvides el espacio en blanco entre cada pa
labra clave. Naturalmente, es posible limitarlo an ms. Si
slo queremos mostrar el nombre y el apellido
de todos los barceloneses, escribiramos:
Para mostrar todos los datos de la tabla direccio
nes, escribe el siguiente comando en el campo SELECT Apellido, Nombre FROM direcciones
WHERE Localidad'Barcelona'
SQL:
SELECT * FROM direcciones Maysculas y minsculas
Al hacer clic en OK se mostrarn todos los datos.
Acaso te pareci complicado?
O ""X
o vx .....
I
o ., X
rt,&r,iu.

PliA.a.t T
o c.11o1c1.i.pe,.,r2
CJ ........... l!

C/,.....,.. .,

Mostrar slo determinados campos
No siempre querremos mostrar a la vez todos Es importante recordar que las maysculas y
los campos de una base de datos de direcciones. minsculas no tienen ninguna importancia en
Quizs slo nos interese el apellido. O el apelli estas consultas. Si por error hemos introduci
do y el nombre. En cualquier caso, no hay pro do en la base de datos barcetona, aparecera
blema. igualmente en los resultados de la bsqueda.
Si slo queremos mostrar el apellido, bastar con Sin embargo, no se reconoceran otros agre
escribir: dados a la palabra Barcelona: no se reconoce
SELECT Apellido FROM direcciones ran los contactos de BarcelonaPedralbes o
BarcelonaEixample. El signo igual significa que
Prubalo: solamente se mostrar la columna con
solamente se permite esa cadena de carac teres,
los apellidos, mientras que las dems columnas
sin importar si est en maysculas o
quedarn ocultas.
minsculas.
BJ s.ni1dor1 loc:lhost dgb B d dtoa.r .ql_prof1
... Est:ruc:t JI 5lQl '&usca, Dejemos de buscar a los arrogantes barceloneses
y busquemos a nuestros amigos del campo o,
mejor an, de Campolandia. Supongamos que
Campolandia estuviera dividida en Campolan
dia N orle, Campolandia Sur y Campolandia Es
Introduce los comandos SQL directamente en el cam te.
po SQL.
Mostrar, filtrar, ordenar y vincular datos 37
Con Localidad=' Campolandia solamente se
I
El operador LIMIT
mostraran aquellos contactos que vivan en
Campolanda, mientras que con Locali Seguro que ya te habrs dado cuenta de que
dade ' Campolandia Este' solamente encontra
phpMyAdrnin agrega a todas las consultas la
ramos a los habitantes de la zona este. palabra clave LIMITO, 30. Esta clave se utiliza
para mostrar nicamente los prmeros 30 da
Sin embargo, seguimos sin resolver el enigma: tos de la tabla. El prmer valor corresponde a
cmo podemos "agrupar bajo un solo para la cadena de caracteres inicial. El contador se
guas" a todos habitantes de Campolandia? inicia en O, igual que ocurre con las arrays in
dexadas.
El operador LIKE Por el contrario, el segundo valor define cun
tas cadenas de caracteres se desean ver a la
Para estos casos, utilizaremos el operador LIKE, vez. Si queremos ver los siguientes 30 datos,
que significa COMO. En conjuncin con el co escribiramos el mismo comando SQL y le
modn %, este operador brilla en todo su es aadiramos sencillamente LIMIT 30, 30.
plendor.

El signo % se utiliza como comodn para uno


o varios caracteres. Ordenacin
La siguiente consulta: Tambin es posible ordenar los datos. Para ello,
basta con utilizar el comando ORDER BY. En el
SELECT * FROM direcciones WHERE
Localidad LIKE '%Campolandia% siguiente ejemplo, ordenaremos la libreta de di
recciones por los apellidos. La siguiente estruc
devolver todos los datos en los que el campo tura te ayudar:
Localidad est relacionado con Campolandia.
ORDER BY Apellido
Personalmente, suelo utilizar el operador LIKE
El comando SQL completo sera:
para programar funciones de bsqueda ms
sencillas. SELECT * FROM direcciones ORDER BY Apellido
Los datos se ordenarn automticamente en or
den alfabtico ascendente.
Vincular criterios
Ordenacin segn varios criterios
Naturalmente, tambin es posible vincular va
Otra posibilidad es ordenar los datos conforme a
rios criterios de seleccin. Para ello utilizaremos
varios criterios. As, por ejemplo, si queremos
los operadores:
ordenar por localidades y, dentro de cada locali
AND (de Y) dad, por el apellido, la instruccin ORDERBY
OR(deO) correspondiente sera:
En prmer lugar, probaremos el operador AND. ORDER BY Localidad, Apellido
Si queremos mostrar todas las personas de Bar La ordenacin principal se regir por la locali
ceona que se llamen Martnez, escribiremos: dad. Es decir, se mostrarn las localidades orde
SELECT * FROM direcciones WHERE nadas alfabticamente. Dentro de cada locali
Localidad='Barcelona' ANO dad, los datos se ordenarn alfabticamente por
Apellido='Martinez'
el apellido de cada contacto. No est nada mal
Si, por el contrario, queremos ver todas las en esto del SQL. ..
tradas de personas que vivan en Barcelona o que
se llamen Mantnez: Invertir el orden
SELECT * FROM direcciones Si lo que quieres es invertir la ordenacin, es
WHERE Localidad='Barcelona' muy sencillo. Basta con agregar al final de la ins-
OR Apellido='Martinez'
truccin la palabra clave DESC. DESC significa
La bsqueda devolver todas las personas que descending, es decir, descendente.
vivan en Barcelona y tambin todos los que se
apelliden Martnez que no vivan en Barcelona.
38 Mostrar, filtrar, ordenar y vincular datos

Para ordenar todos los datos por el apellido en


orden alfabtico descendente, escribe lo siguien
te:
SELECT * PROM direcciones ORDER BY Apellido
DBSC


!- .......,1
-
M. - -----------l

o.,
n ..... k,r(li,nt"el
c.,,,.n\nr111n I

"'-
31
JiiiW ')O 111" .......
,r .,..i llln111f'
T- P"(..il.t
Y

w
e . ._. Ol8'N -

t3'

c1i..., .... .. i. noef' .,_...,, ,..


a/ -x-,.. .. ......,, ,:r HllCt' .._.,.,., ,.,.

_/)( . ,.
phpMyAdmin muestra la ordenacin de forma grfi
ca
phpMyAdmin volver a introducir automtica
mente el comando LIMIT.
Consultas con JOIN 39

Consultar dos tablas simultneamente


con JOIN
a., .tinn C.llt, de l. iaoso S..,,:elo11a 931234567 63&1234,,6
....
Gl9r.s@mlmartlrMZ.e

. -u.
P,1t.
c. d '- 08001 S.tulone 9386!1889'1 fftS63671t P."Dbc>t.jJe,com 2 & un Mfflbre
Nbida, 13

' " , m"'
, .... T o.afiet ct .1a11, 08036 beraiJon
93<l,t::1908 63&678549 g,..:bk,
flllo ollcl .u
" cumi,l.."""Jt

De este modo, no es necesario rellenar nue


Dos tablas vinculadas vamente los datos del cliente por cada nuevo
pedido realizado.
Bien, por ahora todo funciona. Pero realmente
te convence la forma de mostrar los datos de la Esta divisin en varias tablas se conoce como
libreta de direcciones? En lugar de la categora normalizacin. La regla de oro dice que las
slo se muestra un nmero, lo cual no es nada tablas grandes deben dividirse en tablas ms
indicativo ... pequeas siempre sea posible.
No sera mejor que en lugar del nmero identi No tendra mucho sentido guardar "por sepa
ficador se mostrase directamente el nombre de la
rado" el Tratamiento, por ejemplo. Ya que en el
categora? Vamos all.
caso de Sr. y Sra., la normalizacin supone un
Bases de datos relacionales esfuerzo mayor que la posible recompensa.
Tampoco es cuestin de exagerar.
Por ahora, hemos dividido nuestra libreta de
direcciones en dos tablas distintas, ya que es
una organizacin ms racional. Entre la tabla
direcciones y la tabla categoras hay un vnculo,
Join entre tablas
una relacin. El hecho de almacenar las cate
goras en una tabla separada nos permite ges Cmo podemos encadenar ambas tablas al
mostrar los datos? Para ello se utiliza un join.
tionarlas ms fcilmente. As, si queremos
Basta con escribir un comando SQL que tome las
cambiar el nombre de la categora Compaeros
columnas correspondientes de ambas tablas. En-
de trabajo por Trabajo, gracias a que tenemos seguida lo vers ms claro.
dos tablas separadas no supone ningn pro
blema. Slo tendramos que aplicar el cambio Para nuestro ejemplo, necesitamos todos los
campos de la tabla direcciones excepto Categora.
en la tabla categoras, y listos. Por el contrario,
En lugar de utilizar el nmero identificador,
si hubisemos introducido las categoras di
mostraremos el campo ms "amigable" Categora
rectamente en la tabla de direcciones, habra de la tabla categoras. Para ello es necesario escri
mos aumentado el riesgo de cometer posibles bir los datos de una forma especial, con una no
errores; imagina que la tabla tuviese 10.000 tacin con puntos: categoras.Categora ya que
entradas ... En los sistemas de compra tam hemos utilizado el nombre de campo "Catego
bin se suelen dividir los datos en una tabla ra" tanto en la tabla direcciones como en catego
de pedidos y una tabla de clientes. ras (Atencin al acento! El nombre de la tabla
40 Consultas con JOIN
categoras no lleva acento; el nombre del campo En la siguiente lnea se seleccionan ambas tablas
"Categora" s) . Slo mediante esta asignacin, y se vinculan mediante "FULL JOIN": FROM
el intrprete entiende que nos estamos refiriendo direcciones JOIN categorias
al campo Categora de la tabla categoras.
Para terminar, mediante la clusula WHERE de
Por el mismo motivo utilizamos tambin la sin fino qu datos quiero ver: aquellos cuyo nmero
taxis con puntos en direcciones.id. Tambin aqu de Categora de direcciones coincida con el id de
es necesario evitar cualquier doble sentido. Los categoras. Y solamente esos, ninguno ms.
dems nombres de campo no requieren ninguna
"indicacin de ruta", por lo que no es necesario
especificarlos mediante puntos.

SELECT direcciones.id, Tratamiento, Nombre, Apellido, Calle, CP, Localidad, Tel, )


Mvil, Mail, Website, categorias.Categora, Notas
FROM direcciones JOIN categorias
WHERE direcciones.Categora categorias.id
LEFT JOIN

41

Que no te pase nada por alto: uso de


LEFT JOIN
Supongamos que en la tabla direcciones quedase Cuando se utiliza un LEFT JOIN, se lee siem
un campo de categora vaco. Imagina que te has pre por completo la tabla de la izquierda, de
olvidado de introducir una cifra en el campo, o modo que nunca falta ningn dato. En nues
que no pudiste decidirte por asignar una deter tro caso, la tabla de la izquierda es la tabla di
minada categora al contacto. recciones. Es decir, izquierda no es otra cosa
Sin embargo, tambin podra ser que no se en que la izquierda del comando LEFT JOJN.
cuentre ninguna coincidencia con nuestra lista
de categoras porque hubieras introducido un A continuacin, con ayuda de la palabra clave
nmero incorrecto. ON se "organiza" la comparacin de los campos
correspondientes.
Los lmites de MySQL
Desgraciadamente, MySQL no soporta las co SELECfid ,......,... ......,.. C... CP
1
w.t: ..._, Ml:lm.

....
Tef WiMI
nocidas claves ajenas que se pueden encontrar
en otros programas de base de datos. En la 1.EFT' ........ ONC....., .. ili
'
prctica, significa que es posible introducir "' 1
cualquier nmero en el campo Categora.
MySQL no comprobar si la categora intro 1
ducida se corresponde realmente con la cate
gora de la tabla categoras. Tendrs que poner
mucha atencin al introducir datos, o bien,
.
LEFT JOIN lee la tabla de la izquierda por completo
y muestra todos los datos, incluso los que no tienen
una categora
cuando ms tarde programes una interfaz pa Es decir, se mostrarn todos los datos de la tabla
ra la introduccin de datos, escribir un script izquierda, aunque no se encuentre ninguna co
que slo permita valores correctos. No te pre incidencia. En ese caso, en el campo categora
ocupes, nos ocuparemos de ello. simplemente aparecer un O; as de sencillo.

Nuestro "Full [oin" de la pgina anterior tiene


un truco decisivo. Solamente nos muestra los
datos que tienen asignada una categora. Haz la
prueba: introduce una direccin sin asignarle
una categora. A continuacin, realiza nueva
mente la consulta que te he propuesto en la p
gina anterior.
Observars que el nuevo dato no aparece. Por lo
visto, no era tan fantstico nuestro Join con la
clusula WHERE ...

I En estos casos se necesita un LEFT JOIN.


No me estoy refiriendo a nada relacionado con
la poltica, sino con la tabla izquierda.
Analiza el comando que te muestro al final de
este captulo (pgina siguiente) y compralo con
la variante "FULL JOIN" del captulo anterior.
Ejercicios sobre SQL Ejercicio 3
Crea una consulta SQL para una lista de telfo
Ejercicio 1 nos. Solamente deben mostrarse los campos Ape
Introduce una nueva fila de datos en la libreta llido, Nombre, Te/ y Mvil.
de direcciones (a mano). Utiliza INSERT
INTO. Ejercicio 4
Ampla el comando de la lista de telfonos de
Ejercicio 2 modo que tambin se muestre la categora como
Ordena todas las direcciones por apellido y, texto.
dentro de los apellidos, ordnalos por
nombre. Muestra rcamente a las mujeres.
42 LEFT JOIN

Ejercicio 5
Introduce un campo de aniversario en la lista de
direcciones, utilizando phpMyAdmin. Utiliza el
tipo de dato para fechas (DATE). Ten en cuenta
que la fecha se debe introducir siguiendo el es
quema 20061203.

SELECT direcciones.id, Tratamiento, Nombre, Apellido, Calle, CP, Localidad, Tel, Mvil,
fJ
Mail, Website, categorias.Categora, Notas
FROM direcciones LEFT JOIN categoras
ON direcciones.Categora= categoras.id
PHPy MySQL 43

PHP y MySQL: mostrar los datos como


pgina HTML
Aqu empieza realmente la accin, y comproba

p
rs que todos estos pasos previos con SQL tenan
su razn de ser. A continuacin, mostraremos la Mostrar nombres
libreta de direcciones dinmicamente como p Clara Martion:
gina HTML.
Feeese Palafef

:
Empezaremos con una vista de los datos estruc
LeoM"""'
turados en filas, y lo iremos complicando hasta Pedro Jimeor:z
una tabla.
Cmo se puede leer con PHP los datos de una
tabla MySQL? Cmo se accede a los datos? En En el primer ejemplo juntamos los nombres y los ape
seguida resolveremos el misterio. llidos
Abajo te muestro el cdigo fuente que he utili
Nombres y apellidos zado para esta consulta. Nuevamente, slo he
copiado la parte del cdigo contenida entre las
Para nuestro primer ejemplo, mostraremos los etiquetas cbodyec/body.
nombres y apellidos de los contactos de la libre Adems, en el suplemento encontrars el docu
ta. Los datos aparecern uno tras otro, separados mento, llamado direccionesl.php.
por un salto de lnea. El resultado tiene este as
pecto:

<h3>Mostrar nombres</h3>
<P>
<?php
$dp = mysql_connect{nlocalhost", erooc v "");

mysql _select _db { "sql _prof i 11 , $dp) ;
$sql = SELECT * FROM direcciones";
11

$resultado= mysql_query($sql);
while ($row = mysql_fetch_assoc($resultado))
echo 11$row[Nombre] $row(Apellido]<br>\n";

mysql_clase ( $dp) ;
?>
</P>

Establecer la conexin Como ubicacin de la base de datos especifica


remos casi siempre localhost. Sin embargo, en
Antes de nada, aparecer la funcin funcin del proveedor de hosting que utilices,
mysql_connect(). Como su nombre indica, esta es posible que tengas que escribir la direccin
funcin se encarga de II conectarse" al web del host. Por ejemplo, en el caso de
servidor de la base de datos. Dreamhost, recuerda que debers usar el
La funcin mysql_connect() acepta tres argumen nombre de host (hostname) que hayas confi
tos. Son los siguientes, de izquierda a derecha: gurado en el panel de control.
ubicacin de la base de datos, nombre de usuario y
contrasea.

44 PHPy MySQL
El nombre de usuario de nuestros ejemplos offline maria as). El efecto final es que se crea una lista
con XAMPP siempre es root, y no se ha asignado de resultados.
ninguna contrasea:
mysql_connect(nlocalhost", "root", ""); Cuestin de resultados
Si deseas probar el script en tu proveedor de Cmo tenemos que imaginarnos ese resulta
hosting, naturalmente tendrs que ajustar estos do? Como una lista. En este sentido, tambin
datos. se suele hablar de result set, es decir, de la lista
de resultados. Una vez ejecutado el comando
Variable como identificador de conexin
SQL, el resultado est a nuestra disposicin
Y qu significa la variable $dp que aparece al
principio de todo? Es una especie de identifica en forma de lista, en forma de "tabla virtual"
dor de conexin para la conexin con la base de en la que todas las filas estn ordenadas una
datos. Es importante si nos conectamos a varios detrs de otra. Lo que haremos es leer esa lis
servidores de bases de datos. En ese caso, se ta, fila a fila.
asigna un identificador propio a cada conexin.
Estoy seguro de que no habrs tenido ningn
Seleccin de la base de datos correcta problema para seguir mis explicaciones hasta es
Despus de la conexin, es necesario selecccio te punto.
nar la base de datos deseada. Por eso, la siguien
te funcin que aparece realiza una seleccin. Bucle para leer los datos
A partir de aqu, las cosas se complican un poco.
El nico argumento realmente necesario es el
Lo siguiente que aparece en el cdigo es un bu
nombre de la base de da tos. Como segundo ar
cle, vinculado con una funcin. De qu se en
gumento se puede utilizar el identificador de la
carga exactamente?
conexin que acabamos de ver, por ejemplo:
mysql_select_db("sql_profi", $dp); El bucle while se ejecutar mientras se cumpla
Ya estamos conectados a la base de datos, y el una determinada condicin.
siguiente paso es proporcionar las instrucciones
SQL deseadas. Como recordatorio, te escribo la sintaxis bsica
de while:
ComandoSQL while (condicion)
A continuacin, guardaremos el comando SQL instruccion;
en una variable. Siendo derrochador como soy,
para este ejemplo opto por seleccionar todos los Al principio del bucle se comprueba si se cum
datos de la tabla: ple la condicin. Por tanto, se comprueba lo si
$sql "SELECT '* FROM direcciones"; guiente:
No es obligatorio llamar a la variable $sql. Lo $row myeql_fetcb_aseoe($resultado)
importante es que recordemos cmo la hemos Qu hace esta nueva funcin?
llamado.
Funcin mysql_fetch_assoc
Ejecutar una consulta La funcin mysqlJetch_assoc() toma nuestra lista
de resultados s decir, nuestra "tabla virtual"-
como argumento.
A continuacin, realizaremos la consulta, llama
da "query" en ingls. Extrae la primera fila de la tabla virtual y la
transforma en una arra y asociativa. En nuestro
$resultado mysql_query($sql);
caso, la array se llama $row, porque ese es el
Transmitimos a la funcin el cdigo SQL que nombre que he decidido asignar a la variable co
hemos almacenado en la variable $sql, y que es rrespondiente:
taba esperando el momento de su salida a esce $row mysql_fetch_assoc($resultado)
na.
Recordatorio: las arrays asociativas se com
El resultado de la consulta se guardar en la va
ponen de un nombre (aqu $row) y las claves o
riable $resultado; (he usado resultado para que
fuese ms explicativo, pero no es obligatorio lla keys. Las keys no son numricas (O, 1, 2, etc.),
sino que permiten asociarles algo.
PHPy MySQL 45

Lo importante aqu es que esta funcin utiliza


los nombres de los campos como key. Para acce
der al campo Apellido, escribiremos
$row['Apellido'] entre dos claudtors
$row[Nombre}. Qu te parece? A que es prcti
co?
Cuando la funcin mysql_jetcl,_assoc() haya ter
miando de leer los datos de la primera fila, salta
r a la siguiente. Y as seguir mientras siga
habiendo filas, almacenando su contenido en la
array $row. Es decir, mientras existan filas, siem
pre se devolver true, y el bucle seguir ejecu
tndose y produciendo cdigo HTML.

El resultado es que el bucle muestra los nom


bres y apellidos de la tabla, y al final de cada
fila se crea un salto de lnea ( <br / > ).

Una vez se hayan ledo todas las filas, se deten


drn la funcin y el bucle. Capito?

Cerrar la conexin con MySQL


Para terminar, cerraremos nuevamente la co-
nexin con MySQL, y para ello podemos utilizar
nuestro indicador de conexin:
mysql_close($dp);
46 Cadenas de datos en forma de tabla

Mejor an: presentar cadenas de datos


en una tabla
Nuestro siguiente objetivo es dar forma a todos los datos de que disponemos, y lo haremos en forma
de tabla HTML. Al fin y al cabo, lo que nos interesa es aprovechar todas las ventajas del HTML. To
dava recuerdas cmo se crea una tabla? En esta ocasin, te presento primero el resultado grfico se
guido del cdigo fuente, y lo analizaremos en profundidad despus.
i\lostrar nombres

idTnt110 JNobn Apellido c,u. CP l.oalidad Ta :\1<hil

,... 'We.;ie

,-.fwww.bQkla.eom
C:11ori:1

11111
!"{otu

bombu muy

Cllllidad de li.s: 5

s... a.. ,u. ...


"'""""" 931234567
Cdelapera.12 lo8080
636113456 1

Pmeo de la'*". 2 916193456


s.

...
I

u S..
s...

IT= .......
=.a. CI de la bebida. 13 loSOOI
"'"""""
9J86jg&97 66186:36711

l CJ A,i>au, 8) knOJ6
""'"""
934SIS908 63667SS49 cr=@w.doo.es l No oMdar su anplea&>s!I

' S.. u CJ Lep,do, 46 escu 9).5308976 1896785 "--- htlpllwww .leoleo OOlll 1
'
Daremos forma de tabla a los datos. La primera fila de la tabla queda resaltada en negrita.
He guardado el archivo del suplemento como direcciones2.php. Como siempre, solamente copio aqu la
parte del cdigo contenida entre las etiquetas <body></body>.

1 <h3>Mostrar nombres</h3>
2 <?php
3 $dp;;. mysql_connect(11localhost11, "zootv , "");
4 mysql_select_db("sql profi", $dp);
5 $sql = "SELECT * PROM direcciones 11;
6 $resultado = mysql_query($sql);
7 $campos = mysql_num_fields($resultado);
8 $filas = mysql_num_rows ($resultado);
9 echo "<pcCant .dad de filas: <b>$filas</h></p>\n11;
10 echo 11 <table boxde re ' 1' cellspacing=' O'> \n"; / / Empezar tabla
11 echo 11<tr>"; // Crear fila
12 for ($i "" O; $i < $campos; $i++) {
13 $nombrecampo = mysql_field_name($resultado, $i);
14 echo "<th>$nombrecampo</th> 11;
15
16 echo "</tr> \n"; / / Cerrar fila
17
18 while ($row = mysql_fetch_assoc($reultado))
19 echo "e t r " // Crear fila
20 foreach ($row as $key => $value) {
21 echo "<td>$value&nbsp;</td>";
22
23 echo "</tr>\n"; // Cerrar fila
24
25 echo 11</table>\n"; // Cerrar tabla
26 mysql close ( $dp) ;
27 ?>

Cadenas de datos en forma de tabla 47

Campos y filas Para que el bucle tenga una condicin de inte


rrupcin, primero he tenido que determinar la
Lo primero que hacemos es determinar la canti
dad de campos y de filas. Esto ocurre en las l- Si escribimos un O como indice, la funcin de
neas 7 y 8, donde las estrellas invitadas son las volver el primer nombre de campo, en nues
funciones: tro caso id.
mysql_num_fields() y
mysql_num_rows() Por tanto, necesitamos un bucle que recorra to
dos los campos de la tabla y extraiga la informa
Estas funciones toman la lista de resultados cin.
de la variable $resultado y la analizan.

El resultado del anlisis se almacena en las va


riables respectivas $campos y $filas. En la lnea 9
encontramos el primer uso de esta variable, que
me permite mostrar la cantidad de filas de da
tos.
En la lnea 10 empezamos a crear la tabla, con la
etiqueta inicial <table>.

Dicho sea de paso, para que los bordes de la


tabla sean bien finos, utilizo los pares atribu
tovalor border='1' cellspacinge'D',

En la fila 11 empiezo la primera fila de la tabla,


pero qu ocurre despus?

Mostrar los nombres de los


campos
A continuacin recuperamos los nombres de los
campos, es decir, id, Apellido, Nombre, etc. De ello
se encarga esta linea:
mysql_field_name($resultado, ndice)
Como podemos ver, como primer argumento
volvemos a utilizar nuestra querida lista de re
sultados $resultado.
Sin embargo, qu papel juega el valor indice
que se utiliza como segundo argumento? La
funcin no devuelve todos los nombres de cam
po de una sola iez. Solamente muestra los nom
bres de campos que se ajusten al valor indice in
dicado.
cantidad total de campos en la linea 7.
Soy demasiado perezoso como para escribir
Seguro que recordars el concepto del bucle for una lnea echo con todos los cdigos
... de no ser as, te recomiendo que consultes <fd>$row[id]</td><td>$row[Apellido]</td>
de nuevo el cuaderno anterior, "PHP 5". En ese <td>$row[Nombre]</td> etc.
ttulo habl largo y tendido sobre los distintos
tipos de bucles. Con el bucle foreach recorremos toda la array
$row y podemos acceder a todos los $values al
macenados en ella, es decir al campo id, Apellido,
Mostrar las filas Nombre, etc. Si tienes dudas sobre la sintaxis de
este bucle, puedes resolverlas en el cuaderno an
Ya tenemos los nombres de cada campo, que terior.
gracias a las etiquetas <th></ th quedarn re
saltados con respecto al resto de celdas de la ta &:nbsp; como comodn
bla. Hemos cerrado toda la fila en la lnea 16 Para qu utilizo realmente el "non breaking
con la etiqueta </tr>. space", es decir el carcter HTML &:nbsp; de
A continuacin, presentaremos cada uno de los la linea 21? Seguramente tambin podra
datos, y con ellos, las siguientes filas de nuestra haber escrito <td>$value&nbsp;</td> sin este
tablaHTML. espacio en blanco protegido. Es cierto, pero
este espacio en blanco "me protege" frente a
El procedimiento que he utilizado en la lnea
18 debera resultarle familiar. Ya conocemos el posibles campos vacos. De lo contrario, las
bu cle while del ejemplo anterior. La lnea 19 celdas vacas apareceran "vacas" y "sin mar
tam poco tiene ningn misterio, ya que en ella co".
crea mos una nueva fila de la tabla. Pero
despus aparece un nuevo bucle, para qu? Las siguientes lneas de cdigo cierran la fila de
la tabla y despus la propia tabla.
48 Cadenas de datos en forma de tabla

Mostrar la categora como


texto
Un momento! No deja de ser un poco tonto que
en la columna Categora siga apareciendo un
crptico nmero identificador. Para qu sino
hemos aprendido antes a utilizar LEFr JOIN ...
Desplzate hasta la lnea 6 del cdigo y cambia
el valor de la variable $sql por el cdigo de la
pgina 41. Funcionar a la perfeccin:
$sql "" 11SBLBCT direcciones. id, tJ
Tratamiento, Nombre, Apellido, Calle, d'
CP, Localidad, Tel, Mvil, Mail, tJ
Website, categorias.Categora, Notas
PROM direcciones LEFT JOIN categorias
OH direcciones.Categora categorias.id11;

Encontrars el resultado en el archivo direccio


nes3.php.
Ms seguridad para la conexin MySQL 49

Ms seguridad para la conexin MySQL


Aunque nuestro sistema para crear una tabla ha la columna derecha de esta pgina:
funcionado, todava no es demasiado profesio
nal. Ha llegado el momento de solucionar un $dp = <tmysql_connect ( 11 localhost", di
"zoot v , 1111

par de problemillas.
);

mysql_select_db ( "sql_profi", $dp);

Recordatorio: la primera funcin establece la co


Evitar los mensajes de error nexin con el servidor MySQL, y la segunda se
lecciona la base de datos deseada.
El primer problema es muy fcil de simular.
Basta con introducir unos datos de usuario err No est nada mal, pero esta solucin tampoco
neos en la lnea de cdigo $dp = mysql_connect es definitiva, ya que no hemos logrado desac
.... Si, por algn motivo, la conexin con el tivar los mensajes de error de las dems fun-
servidor MySQL no funciona, aparecera una ciones. Adems, al desactivar estos mensajes
ventana lle na de mensajes de error: no sabremos cul es el problema. No se ha
logrado establecer la conexin con el servi
dor? Hay un problema con la base de datos?
..... ..yj._-..() !&r:izn rnll2 1t. Acto< &aled r.:,,. ._- 'roa,:,( ('*'I
pu1Mffl NO) .. C,\l<fliud>lnmpp\l,ldoal,lpl:ldhccloHtJ,plip"" 1Dc 19

Wa,..'-a .t,Q:....-.,.i;.O<!CY!OldMySQt.Looi<<.........,.k
Desactivar todos los mensajes de error no tiene
c,1.apo<hfli.tN1\Ja-ii,1ltd0<al,lr,plWlr11,tcl<>ll d,p "".., L ningn sentido, necesitamos controlar exacta
\\'oro.Ita ...,.,..._"'"'1() limooe,mra<f:IMO't Ac:C<'U d(lliod for,.... 'QOBC"@ Q'5lo& mente lo que ocurre cuando se interrumpe la
Jl'lfW'll"l NO) lo C;\lparlofmhl.uPl'\l.!docpl\dlrtlo-..2.fd,p ,- ... ll
ejecucin del cdigo.
La conexin no funciona: mensajes de error.
Sin embargo, estos mensajes no son de mucha Control de errores con or die()
ayuda, ni para uno mismo ni para los usuarios.
Lo que haremos es desactivarlos. Para detener un script, podemos utilizar las pa
labras clave exit y die(). A diferencia de exit, die()
Coloca el signo de la arroba @ delante del permite mostrar en pantalla un mensaje perso
nombre de las funciones. nalizado.

La arroba permite evitar que se muestren los die() queda especialmente elegante si se com
mensajes de error de la mayora de funciones. bina con el operador or.
En nuestro ejemplo, las "lneas de acceso" ten-
dran este aspecto; observa la parte superior de Es decir, escribe lo siguiente:
$dp = @mysql_connect(11localhost11, "zoot", "11 ) or die("<p>No se ha podido establecer;
la conexin con MySQL.</p>");
@mysql_select_db ( "sql_profi" , $dp) or die ( "<p>No se ha podido establecer&'
la conexin con la base de datos.</P>");

Si no se logra ejecutar mysql_connect(), se mos Si, por el contrario, la base de datos tiene algn
trar el mensaje No se ha podido establecer la co problema, PHP mostrar el mensaje personali
nexin con MySQL y se detendr el script. zado correspondiente. Prubalo, funciona muy
bien. Sin embargo, no me doy por satisfecho con
i\lostrar nombres
esto. Por algo hemos hablado en la pgina 13 so
No se ha podido establecer la. cQl'.IWO coa MySQL. bre la forma de almacenar los datos del usuario
de forma externa ...

Un problema al conectarse con el servidor?


50 Ms seguridad para la conexin MySQL

Guardar los datos de acceso


de forma externa
Para terminar, te recomendar que guardes las
dos lneas con los datos de acceso de las que aca
barnos de hablar en otra ubicacin, por ejemplo
en un archivo llamado acceso.inc.php. No te olvi
des de incluir las instrucciones iphp y ?> antes
y despus de ambas lneas de cdigo.
Para vincular los datos de acceso externos al ar
chivo, bastar con incluir esta lnea de cdigo:
include(" .. /cgi-bin/acceso.inc.php");

De esta forma logramos mejorar la seguridad.


Con este archivo externo tambin estarnos
creando un mdulo de acceso que podemos
volver a reutilizar ms adelante. En caso de
cambiar de servidor, slo tendrs que cambiar
los da tos una vez, en Jugar de repetirlo en to
dos los archivos.

Encontrars la solucin en el archivo del suple


mento direcciones.php.
Introduccin de datos mediante formularios 51

Introduccin de datos: formulario con


campo de consulta
A continuacin te mostrar cmo crear un for Es decir, la primera vez que se llama la pgina
mulario sencillo para la introduccin de datos. solamente se activa else.
Incluir un mensaje de xito, una comprobacin
rudimentaria de los datos introducidos e incluso Preparar el campo de categora
la recuperacin automtica de los datos de la ta En las lneas 2631 preparo el campo para las ca
bla de categoras. tegoras.

En realidad, estoy creando un campo de con


sulta.

El bucle while crear mediante pares de etique


T n tllllie a&o tas <option> </ option> el men desplegable de
N_ ,

1e....e categoras. Dichos campos <option> se guardan


=
=.

. =..=..fiiiOi
CP
=.....=
=::J
en la variable $campocat. Seguro que recordars
el signo _; del cuaderno anterior, es una abrevia
tura para la autoconcatenacin. Como value se
L
1 , ocW.

introduce el id de la tabla categoras, pero se


M<:,.i: '661654189 1
E-Mal f,-c,..@ .,t,.otamj muestra el nombre descriptivo del campo Cate

:= -
gora.
iaj
:
este modo nos aseguramos de que el usua

f ::. M ..
j,J t -

. i:'3

se establece la variable $_POST['submit'J. Esta


variable se crea con el botn subrnit de la
! -......:4*11
lnea
5354, al que he llamado namee'tsubmit", Por tan
Introduccin de datos mediante un formulario to, la parte if slo se activa una vez enviado el
formulario; de lo contrario entra en accin else.
Encontrars el cdigo fuente correspondiente a
este ejemplo en la pgina siguiente, donde he
copiado el cdigo contenido entre las etiquetas
<body> </body>. El documento del suplemento
se llama introduccion.php.

Anlisis del cdigo fuente


Todo empieza en la lnea 3, dqnde vinculo los
datos de acceso a MySQL almacenados de forma
externa. El script contina en la lnea 4 con una
larga consulta if que se divide en la lnea 25 en
else. La condicin else se mantiene prcticamente
hasta el final, hasta la lnea 57. Podrs identifi
carlo fcilmente gracias al sangrado del cdigo.
Qu comprueba la consulta if? Comprueba si se
ha enviado el formulario, ya que slo entonces
De
rio vea el texto Privado, pero en la base de da- Validacin del formulario
tos se introduce l. Y tambin nos aseguramos
Una vez enviado el formulario se activa la con
de que el usuario solamente pueda introducir
dicin if de la lnea 4. Las lneas 59 "se encar
valores que ya existan en la tabla categoras. gan" de comprobar los datos de forma rudimen
taria. En la linea 5 compruebo si el campo Nom
Crear el formulario bre est vaco. De ser as, muestro un mensaje de
error.
El cdigo del formulario no tiene ninguna otra
complicacin: utilizo la cmoda sintaxis heredoc En el caso del apellido en la lnea 7 soy ms es
y los campos de formulario HTML: la mayora trico, y obligo a utilizar un mnimo de 3 caracte
son simples campos de introduccin de texto, y res. De ello se encarga la funcin strlen(Variable).
hay dos mens desplegables.
strlen() devuelve la longitud de una cadena
que se comprueba en una comparacin.
52 Introduccin de datos mediante formularios
Si se superan las dos comprobaciones se activa Entre el segundo par de parntesis es necesario
la parte e/se de la lnea 9, que se alarga hasta la especificar todas las variables $_POST, exacta
22. Aqu es donde se realiza la introduccin de mente en el mismo orden que los nombres de los
datos. campos que acabamos de introducir en el primer
parntesis. Y todo ello bien rodeado de comillas
simples.
Introducir datos: INSERT En la lnea 16 ejecuto la consulta. Y, dado que las
comprobaciones son un trabajo manual, com
INTO pruebo el xito de la consulta en la lnea 17 y
muestro un mensaje de xito o error.
Recuerdas la sintaxis de introduccin de datos
de nuestro curso sobre SQL? Es la siguiente: En caso de error, el usuario puede hacer clic en
el vnculo Volver que se crea en la lnea 23 me
INSERT INTO nombretabla (nombrecampo) diante JavaScript. De lo contrario, haremos clic
VALUES (valores)
en el vnculo Introducir nueva fila que se crea en
Encontrars el comando completo en las lneas la lnea 24.
10 a 15. Entre el primer par de parntesis incluyo Qu te parece, Je echas un vistazo?
todos los campos, excepto id. No Jo necesito
porque se crear automticamente.

1 <h3>Introducir direcciones</h3>
2 <?php
3 include (" .. /cgi-bin/acceso. inc .php") ;
4 if (isset($_POST['submit])) {
5 if (empty($_POST['NombreJ)) {
6 echo "cp s Irrt r oduaca el cbonornbre e Zb s . </p>11;
7 ) else if (strlen($_POST['Apellido'])<3)
8 echo <p>El apellido debe tener como mnimo <b>3</b>
11
tJ
caracteres. </P> '' ;
9 } else {
10 $sql = INSERT INTO direcciones (Tratamiento, Nombre, Apellido,
11
Calle,
11 CP, Localidad, Tel, Mvil, Mail, Website, Categora, Notas )
12 VALUES ('$_POST{Tratamiento) ', '$_POST[Nombre] 1
,
1
$_POST[Apellido] ',
13 '$_POST[Calle] ', '$_POST[CP] ', '$_POST[Localidad] ', '$_POST[Tel] ',
14 '$_POST[M6vil] ', '$_POST[Mail] ', '$_POST[Website] ', '$_POST[Categora]'
15 '$_POST [NotasJ ') 11
;

16 $resultado mysql_query{$sql);
17 if {$resultado) {
18 echo "<P>Datos agregados con xito. </p>";
19 else (
20 echo "<p>Datos <b>nO</b> agregados. </p>";
21
22
23 echo 11
<a href:1javascript:history.back() '>Volver</a> l -
[

24 <a href:'$_SERVER[PHP_SELF) '>Introducir nueva fila</a> )";


25 else {
26 $sgl2 "' SELECT * FROM cat.eqoz-Lasv,
11

27 $resultado2 mysql_query{$sql2);
28 $campocat == "11;
29 while ($row = mysql_fetch_assoc($resultado2))
30 $campocat . "' "e opt.Lon value= 1 $row [id] '>$row [Categorial </option>\n";
31
32 echo <<<FORMULARIO
Introduccin de datos mediante formularios 53

33 <form action="{$_SERVER[1PHP_SELF1] }" tne t.hode vpoe t ">


34 <table>
35 <tr><td>Tratamiento:</td><td><select name=11Tratamiento">
36 <option>Sr.</option>
37 <option>Sra.</option>
38 </select></td></tr>
39
40 <tr><td>Nombre: </td><td><input type="text" name="Nombre" ></td></tr>
41 e t r s e t dcApe l.L.do : < /f.d s c t ds e .nput; type= 11 text II name="Apellido" ></td></tr>
42 e trr se t.dcCa L'l e : </td><td><input type= 11 text O
name= "Calle" ></td></tr>
43 <tr><td>CP:</td><td><input type= text" name=11CP11></td></tr>
11

44 c::tr><td>Localidad: </td><td><input type=" text II name= "Loce.Ld dad" >c::/td>c::/tr>


45 c::tr>c::td>Tel:c::/td><td>c::input type="text11 name="Tel"></td></tr>
46 c::tr><td>Movil:</td><td><input type="text11 name=11M6vil"></td></tr>
47 <tr><td>E-Mail:</td><td><input type::::"text11 name=11Mail11></td></tr>
48 <tr><td>Website: </td><td><input t.ype e t' t ext;" name=11Website11></td></tr>
49 e t r s e t dc-cat.eqor La : </td><td:::.<select name= vcat.eqor-La 11 > { $campocat) </ (
50 select>
</td></tr>
51 <tr><td:::.Notas:</td><td>
52 <textarea cols=116011 rows:::11411 name=11Notas11></textarea></td></tr>
53 <tr><td></td><td>< input type=" submit" value=" Introducir datos"
54 name=11submit11></td></tr>
55 </table>
56 </form>
57
58 FORMULARIO;
59 mysql_close ($dp);
60 ?>

Pero es posible ponerle fin con MySQL. Slo te


Evitar un posible reload nemos que aseguramos de que varios campos
nunca compartan el mismo valor. Por ejemplo,
Como siempre, no me doy por satisfecho. es muy improbable que dos personas tengan el
Imagina que introducimos una entrada y hace mismo nombre y apellido, y que vivan en la
mos clic en el botn Recargar (o Actualizar) del misma calle y en el mismo nmero.
navegador ... y lo hacemos otra vez ... cada vez
que hacemos clic, introduciremos nuevamente la I Convierte estas tres columnas en UNIQUE
misma direccin. Excepto por su id, todas las di INDEX.
recciones sern iguales.
l. Abre phpMyAdmin y accede a la tabla direc
Si eso ocurre, habrs cado en el problema del ciones.
reload.
2. Antes de nada, elimina las posibles direccio
nes duplicadas, ya que de lo contrario no
funcionara el invento.
Continuar
54 Introduccin de datos mediante formularios

3. A continuacin, haz clic en la ficha de men


Estructura. Observa el campo Crear un ndice
y escribe la cantidad de columnas deseada,
en nuestro caso 3.

Nomt.r. decl lndke, '-------


L). ("PRIMAR.Y" ...duW'.11,,,.11tffH 11., el n,ombt.


Tlpo d n.dto. , 1 UN [QUE j f!l

C..m ... ,
Nombnl. [vr(2:5)]

"I1[4-1;..*:a m l CJ:
AIM!l!idQ (v...:;hr(:U}I

Alladit I ndic. []
2

coh,m,..{) 1

Cantln....,.
1

4. En la pgina siguiente, deja vaco el campo


Nombre del ndice. En Tipo de ndice selecciona
Llnique. Debajo debers seleccionar los tres
campos Nombre, Apellido y Calle.
5. Para terminar, haz clic en el botn Grabar.
De este modo ya no podremos introducir dos
veces seguidas los mismos datos. La funcin
mysql_query() de la lnea 16 devolver false y la
lnea 20 te informar sobre el problema.


Copia de seguridad de tablas 55

Crear copias de seguridad de tablas


y transferirlas a otros equipos
Una de las cosas que ms me gustan de MySQL 3. Selecciona las opciones SQL desedas. Si lo
es la facilidad con la que se pueden traspasar da que se desea es sustituir tablas antiguas, vale
tos de un ordenador a otro. la pena seleccionar Aadir 'DROP TABLE';
por lo dems, no hay que hacer ningn otro
Offline: en un PC local cambio.

A,iadir 'DROP TABLE' significa que la tabla se


mysql En los PC locales no eliminar antes de copiar los datos. Es ideal
E!I C) backup supone ningn problema, para volver a empezar desde cero.
e) bin ya que tenernos acceso
EJE:illll directo a la carpeta de la
4. Activa la casilla Enviar y haz clic en Conti
e) cdcol base de datos en el sistema
el ctm de archivos. Los datos se nuar. De esta forma se guardar el comando
e) editor encuentran en una carpeta SQL completo en un archivo que podrs
e) feedback llamada mysql/data. En el "descargar" a tu ordenador.
C)
e)
fotoalbum
fotogast
caso de nuestra instalacin
de XAMPP, encontrars I El archivo resultante tiene la terrninacii;(.sq(
e:, kunden todos los da tos en
e) kw xampp/mysql/data. Puedes 5. Guarda el archivo en tu PC y recuerda la
e) kw.alt copiar todas las sub carpeta. Si ests realizando una copia de se
el mysql carpetas y pasarlas a otro guridad completa del servidor web, la des
C) phpmyadmin equipo con XAMP. Por lo carga puede durar bastante.
e) sql_profi menos en mis intentos,
siempre ha funcionado a la Para recuperar los datos, basta con acceder a la
C) team seccin Importar y seleccionar el archivo .sql.
perfeccin.
c:!I test Importar
le) webauth
r
loGl!!ucln dI ..:hlvo d t.xto \Ooo.imlrisa'ld !&-,!! 11 (Tr

Ju990 se carctiit:ra9 dI archivo, j utf8 1


l..ii comp,,a,slri C09d para el an:hN<1 a lmpo,tiu det.<:u,rA autom.6tla

Online: mediante SQL-Dump


l:>Q_...

E'.] Pwmibi la fnt-rupdn de la lmj>Qtt.cI'! an al c,n;o de qua al Ktlpt da


.., un b.._.n m4b:w:1<1 pllJ'II lmport.llr ateh"'041 (randa., In amb.argo, pu..:!

[ ' - .. .. .- - .
Qu ocurre en el caso de los proveedores de
hosting? Por lo general, no tendremos acceso di NU ..,.,. , d" d l 1nlclo la
recto a la carpeta MySQL. @SQI.

. .. . . . . . - - -
d a ,- g ! . b ' otl

y - ,
(co,;lu) a u luor t1
2. Selecciona una a una las bases de da tos que
En situaciones corno esta, lo que se suele desees exportar o bien haz clic en Seleccionar
hacer es transferir los datos con un "SQL todo.
Dwnp". Crea una especie de fotocopia de la
base de datos, un esquema.

Nuevamente, para ello deberemos usar


phpMyAdrnin.
l. Accede a la seccin Exportar haciendo clic en
la ficha de men del mismo nombre.
!L'
Contln
Exportar desde MySQL 5 a
Haz clic en Examinar y selecciona el archivo MySQL4
Al hacer clic en Continuar se ejecutarn los co
mandos SQL del archivo, y se transferirn Imaginemos que lo que deseas es exportar datos
todos los datos a la nueva ubicacin. de una tabla de una base de datos MySQL 5 a un
sistema que todava utiliza MySQL 4. Podra ser
56 Copia de seguridad de tablas
que utilices la ltima versin de XAMPP en tu
equipo local, pero en tu proveedos de hosting Ejercicios sobre tablas
todava est instalado MySQL 4 "clsico".
En ese caso, en el momento de exportar los datos Ejercicio 1:
debes fijarte en la opcin "Compatibilidad con Vincula los archivos introduccion.php (introduc
exportacin SQL". En la lista desplegable, la op cin de direcciones) y presentacion.php (visualiza
cin marcada suele ser "None". Cmbialo por cin de la base de datos) mediante vnculos para
MySQL40. poder saltar cmodamente de una pgina a otra.

Ejercicio 2:
1d1""'- -.,,,..., f-..... -Po-=-... - ,.._
Edita el archivo de presentacin de los datos pa
.............
............
,......... ........ ra que las direcciones se ordenen por el apellido .

==- ' ftl


Ejercicio 3:
Utiliza tambin los campos Calle, CP y Localidad

-... -..-.
l

o - ..... _, _

11dt-
L _ _ i
para validar el formulario de introduccin de di
e
o
0--- recciones.
.... _
0- ...
Ejercicio 4:
-
. . .. .....
o '""
-

,o

-
oa--
a,.;::-;., ;;;;... Crea una tabla para reunir tu coleccin de dis
cos. Utiliza tambin otra tabla distinta para las
categoras. Utiliza un LEFf JOIN y el campo de
c- ... -
c-...-...* .. consulta en el formulario de introduccin de da
_.......... tos.
"'-_-..."
- Ejercicio 5:
" ' ' " .. -.. - -
... - - r - , , Crea una copia de seguridad de todas las tablas
-...
- que hayas creado. Llmala backupDDMMAAAA,
donde DD es la fecha actual, MM el mes y
AAAAelao.
Si la tabla es MySQL 5, selecciona la opcin
MYSQL40 por motivos de compatibilidad, para que
la importacin a sistemas ms antiguos funcione
sin problemas.
Si te olvidas de hacerlo, fallar la importacin en
el sistema MySQL 4, ya que las tablas de bases
de datos MySQL 5 tambin exportan la codifica
cin de los datos, que se puede reconocer por
algo as como collnte latin1_general_ci.


Felicitacin de cumpleaos con cronjob 57

Felicitacin de cumpleaos mediante


cronjob
Si te pasa lo mismo que a rr y siempre te olvi A nuestro script le dar igual si tiene que
das del cumpleaos de tus amigos y conocidos, enviar dos mensajes de correo electrnico o
introduce los datos en una tabla de una base veinte. El nico requisito es que la tabla de
de datos MySQL. Con el script que crearemos la base de datos est albergada en tu servi-
en este captulo, se enviarn automticamente dor web.
los mensajes de felicitacin.
Nuestro script presupone que la tabla con las
clirecciones clispone de los campos Nombre,
-Gr.
-
J ,.IMJY.9M1f.anomn!lo.t.eom., Apellido, Cumpleaos y Mail. La fecha del cum

;,. .fi!'Q iD;


.
;;;.
por. p,.._.,_w
= pleaos debe introducirse siguiendo el esque


ma AAAAMMDD, es decir 19670312.
81.Mde tol;MllProfl, 9 Tllbll: OhcdOnN

c...,. -
8
c...........,
jlllfamr

.........
Crear una neuva columna en
Cl 111 ,...111 Ho
'0 ........... *1

ti .,......, IN\il.Jilll'IIR'l9 SI
:Q: ...... .., ..........u, $f
a e... lldn1...Dl"Pl_d

QOP lilllf.....-t;.111
o LOlltld.d nalizar el mensaje de felicitacin de cumplea os
...
.,.........P

con un tratamiento personalizado.

Edita tu tabla con phpMyAdmin: desde aqu La tabla de la que estamos hablando puede
puedes introducir (Insertar) nuevos contactos ser perfectamente una pequea libreta de
direcciones, como la que acabamos de crear
en los captulos precedentes. Sin embargo,
Requisitos para el script tambin puedes usar tu directorio de clien
tes o una lista de empleados que contenga
Antes de poder disfrutar de la comoclidad del miles de registros.
script, es necesario realizar una serie de traba-
jos previos. Para que funcione el envo de e-
mails mediante PHP es necesario que lo
permita tu proveedor de hosting (pero tranqui
lo, suele ser as en la mayora de empresas que
ofrecen PHP). Adems, necesitaremos una ta
bla que contenga como mnimo la direccin de
correo electrnico y el cumpleaos de tus con
tactos.
Si la tabla tambin contiene los campos Nombre
y Apellido, mejor. De esta forma podrs perso
tie- ne que llamarse Cumpleaos, y como
la tabla formato de los datos seleccionaremos el
formato de fe
Ya tienes una tabla de direcciones, pero te
cha DATE. Gracias al formato DATE podremos
fal ta la columna para el cumpleaos? Quizs
ordenar ms tarde la lista de direcciones por
se deba a que no has terminado el ejercicio 5
fecha. Adems, este tipo de datos permite al
... macenar fechas ms fcilmente que si se utiliza
No pasa nada, podemos aadirla posterior un formato de texto como puede ser VAR
mente sin mayor complicacin. Cmo se CHAR.
agre ga una nueva columna a la tabla?
Utilizando la siguiente sintaxis: Vamos all, directos a la tabla. Abre la tabla de
ALTER TABLE nombretabla ADD COLUMN
clirecciones con phpMyAdmin y ejecuta el si
nombrecampo guiente comando SQL en el campo SQL:
Con esta instruccin se aadir una nueva co- ALTER TABLE direcciones ADD COLUMN
Cumpleaos DATE
lumna automticamente al final de la tabla ya
existente. En nuestro caso, el nuevo campo Si todo ha ido bien, el nuevo campo aparecer
en la estructura de la tabla.
58 Felicitacin de cumpleaos con cronjob
preocuparte por los problemas del efecto 2000,
ya que este tipo de datos acepta fechas entre
IMYll or.- 01.01.1000 y 31.12.9999 .

...... d-.141l..Jlfolh. Tloblt.:dlr'llcdonff

- _, .. ..
-- "'
2
9
3
10

11
16 17 18

_ .......,.., 111WCt11111_ AICIL r"'ur

;
Q 61 . 1111

,:,jll-- _....... ...,., ,COpeNdDIIN J\lr'

Con ADD COLUMN puedes agregar una nueva Las nuevas versiones de phpMyAdmin proporcio
columna en la tabla direcciones. Usaremos el campo 23 24 25
cumpleaos para almacenar la fecha.
Repito: presupongo que tu libreta de direccio
nes tiene un campo llamado Cumpleaos. Escri
be la fecha del cumpleaos de tus contactos, y nan un campo de seleccin para la fecha que
no te olvides de utilizar el formato AAAA permite introducir la fecha con total comodidad;
MMDD; es decir, empieza por el ao con cua pero no te olvides de seleccionar el ao correcto.
tro cifras, seguido del mes y el da con dos ci
fras. No te olvides de los guiones que separan
los nmeros de la fecha. Tampoco tienes que

Cdigo fuente de cumpleanyos.php


A continuacin, te presento el cdgo fuente completo del archivo cumpleanyos.php. El archivo acce
so.inc.php es el que ya conocemos el ejemplo anterior, que contiene los datos de acceso a la base de da
tos.
<?php
$dia = date ( "d");
// Comparar dia con valor del archivo
$archivo"" 11numerodia.txt11;
$fp = fopen($archivo, r+11);
$aw = fgets($fp, 3);
rewind ($fpl ;
if ($aw ""= $dia)
// Coincide?
$writemail = false;
else {
fputs($fp, $dia);
$writemail = true;

fclose($fp);
// Ejecutar solo el script de mail si lafecha es nueva
if ($writemail) {
include(" .. /cgi-bin/acceso.inc.php");
$mes= date("m'');
$anyo ,,. date ("Y");
$remitente= "tunombre@tuemail.com";
// Asunto del contacto
$asuntol = "Felicidades por tu cumpleaos";
// Asunto para uno mismo
$asunto2 = 11Atenci6n! Se ha enviado mensaje de cumpleaos a:";
// Slo consultar los campos importantes
$sql = "SELECT Nombre, Apellido, Mail, Cumpleaos
FROM direcciones ORDER BY Cumpleaos";
$resultado= mysql_query($sql);
// repasar todas las filas de la tabla:
Felicitacin de cumpleaos con cronjob 59

while ($row = mysql_fetch_assoc($resultado)) {


s
if ( r empt y t row t vna .Lvl j ) {
$cumple= explode(11 -11, $row[Cumpleaos"]);
if ($cumple["211 ] == $dia && s cumpt e Lv " l == $mes) {
// Texto del email, se puede editar
$mailtext .. "Hola, $row[Nombre] $row[Apellido] !

Hoy es $dia.$mes.$anyo!

Te felicitamos de todo corazn por tu cumpleaos


y te deseamos todo lo mejor tanto en tu vida
profesional como personal.

Esperamos volver a verte pronto.

Sinceramente : -) ";
// Final del texto del email
// Enviar mails, incluido mail de control
if {mai1("$row[Mail]", $asuntol, $mailtext, "From: $remitente''))
mail ("$remitente", "$asunto2 $row [Nombre] $row (Apellido] 11,
$mailtext, "From: $row [Mail] 11);
JI cerrar if Mail

JI cerrar if !empty()
// cerrar while
mysql_close(};
// cerrar if writemail

,,
Podemos especificar cundo y con qu fre-
Funcionamiento del script cuencia se ejecutar la tarea, del mismo mo
do que puedes programar libremente el apa
Cmo funciona exactamente este script? Una rato de vdeo para grabar.
vez al da comprobar las fechas de cumplea
os de la base de datos de direcciones. En caso Consulta a tu proveedor de hosting si per
de que coincidan el da y el mes, se enviarn mite la ejecucin de cronjobs. Desgraciada
dos mensajes de email: uno a la persona que mente no siempre es as, aunque el provee
cumple aos, y otro mensaje de recordatorio al dor ofrezca PHP y MySQL. Adems, tu pro
remitente. La idea es que no te sorprendas si veedor podr decirte cmo configurar el
alguien te llama para darte las gracias por feli cronjob. Por lo general, se hace a travs del
citarle por su cumpleaos. men de configuracin del cliente. Si tu
proveedor no soporta cronjobs, una posible
Cmo le decimos al script que compruebe una solucin son los servicios cron gratuitos:
vez al da la base de datos? Los programas de
PHP no suelen ejecutarse automticamente por
www.webcron.or;/jndex.ph;,?&!ang=es o
www.cronjobs.ar. por ejemplo. Sin embar
su cuenta. Para llamar el script, utilizaremos lo go, debers registrarse en todos estos pro
que se conoce como cronjob. veedores con nombre y direccin para poder
evitar eventuales abusos. Por desgracia, en
Cronos es una palabra griega que significa
la prctica muchos de estos servicios gratui
tiempo. Un cronjob no es otra cosa que un tos pueden desaparecer de la noche a la ma
script controlado por tiempo, que p.ej. abre ana.
una vez al da tu pgina PHP. Imagina que
es como la funcin "timer" de la grabadora Si tu proveedor de hosting no permite cronjobs
de vdeo. y no tienes ganas de registrarte en un provee
dor de cronjobs gratuito, tambin puedes usar
lo sin, con nuestro "pseudo cronjob". La nica
60 Felicitacin de cumpleaos con cronjob
condicin es que como mnimo un visitante al Presupongo que el script de PHP (no es obliga
da se deje caer en la pgina en la que se en torio llamarlo cumpleanyos.php), el archivo que
cuentra el script. Para lograrlo, basta con que contiene los datos de acceso a MySQL acce
incluyas el script en la pgina de tu web que so.inc.php y el archivo numerodia.txt ya se en
reciba ms visitas. cuentran en tu servidor.
Coloca el siguiente prrafo PHP en cualquier Sobre todo, asegrate de haber introducido los
punto de tu pgina PHP ms visitada. Tambin datos de acceso correctos en el archivo acce
puedes vincularla con include, por ejemplo: so.inc.php. Y ya puedes probar si el script fun
include ( "cumpleanyos. php") ciona.
El script de felicitacin funcionar de forma
invisible en segundo plano; slo necesita ser Variable $writemail
ejecutado.
Si quieres saber cmo funciona el script para
poder adaptarlo mejor a tus necesidades, lee lo
Una vez al da con pseudo- que sigue: en la primera parte, determinamos
el nmero actual del da de la semana, siempre
cronjob con dos cifras. Para ello utilizo la funcin da
te () en la siguiente lnea:
Parto de la premisa de que tu sitio web tiene
$dia"' date("d");
cierto xito. As, es seguro que tu pgina con el
script de PHP vinculado ser llamada varias A continuacin, abrimos el archivo numero
veces al da. dia.txt y guardamos el valor de dicho archivo
en la variable $aw. Mediante una consulta if
Pero no nos interesa que cada vez que se llame comparamos el da de la semana actual de
a la pgina se enven mensajes de felicitacin. $dia con el valor de numerodia.txi, Si no coinci
Cincuenta mensajes de felicitacin iguales en den, la variable $writemail pasa a ser true. A
un solo da ca usaran en tus amigos una im- continuacin, escribimos el nmero del da de
presin sin duda duradera, pero no muy bue hoy en el archivo numerodia.txi. Si ambos n
meros coinciden, el valor de $wri temail ser
na. Tenemos que asegurarnos de que los men
false y eso ocurrir precisamente cuando se
sajes slo se enven una vez al da, aunque se vuelva a ejecutar el script por segunda vez en
ejecute el script varias veces. Para ello, recurri un mismo da. Es decir, el script ya habr sido
remos a un pequeo truco. El script "se dar ejecutado ese da y no tiene que volver a ejecu
cuenta" del da que es y lo guardar en un ar tarse.
chivo. Para ello sirve precisamente el archivo Las lneas de cdigo siguientes no son nada
numerodio.txt que aparece en el cdigo. complicadas. La parte principal del cdigo so
Para empezar, en este archivo tiene que figurar lamente se ejecutar si el script no se ha ejecu
un nmero distinto al de la fecha de hoy. Por tado hoy. Lo comprobamos con:
ejemplo, si hoy es el 12 de octubre, escribe un if ($writemail) {
11 en el archivo. Guarda el archivo y crgalo en Despus definimos otras variables con las que
el servidor, en la misma carpeta en la que car determinamos el mes y el ao. Y no hay que
gues el script. Ten en cuenta que, en funcin olvidarse de la direccin del remitente y el
del proveedor que utilices, es posible que de asunto. En este caso, distinguiremos entre el
bas cambiar el bloqueo contra escritura para asunto para la persona que recibe la felicita
poder escribir datos en el archivo. Para ello, cin y el asunto del "recordatorio" para ti, el
puedes usar el comando CHMOD 766 o remitente y creador del script. Al fin y al cabo,
se enviarn dos emails.
CHMOD777.
// Asunto del contacto
La primera vez que se llame al script de $asuntol = "Felicidades por tu
cumpleaos";
PHP, ste guardar el nmero correspon // Asunto para uno mismo
diente al da actual en el archivo; en nuestro $asunto2"" "Atencin! Se ha enviado
caso, sustituira el 11 por un 12. mensaje de cumpleaos a:";
Felicitacin de cumpleaos con cronjob 61

Consulta de la base de datos if ($cumple ["2"]


$mes) {
$dia && $cumple ["l"] ==

El texto del mensaje se encuentra entre el par


A continuacin se ejecuta la consulta a la base
de comillas dobles detrs de la variable $mail
de datos, cuyo resultado se almacena en la va
text. Naturalmente, puedes completarlo y
riable $sql. Lo interesante es que en esta con
sulta SQL no se consultan todos los campos de ajustarlo a tus necesidades pero no debes uti
datos, sino nicamente los importantes. En lizar ms comillas dobles en el texto.
nuestro ejemplo, este es el aspecto de la consul
ta SQL:
11' (lfl"'Z"] Ma a 1a1-.,.,..-1, s-,tJ i
$sql="SELECT Nombre, Apellido, Mail,
Cumpleaos FROM direcciones ORDER BY
...._..,_;;:1.7. n*J
Cumpleaos" ;

El resultado se guarda en la variable $resulta


do y est disponible en forma de lista de resul
,)) ..._._. ..cu
,): ....
.
tados, como result set: 111 1 l-.

l.:v .,1), '"' ld,o ,.11 c,,u


,
tt (-1l("'k..0nJ-. ..,_ , ._,r .__ :11'-'t-

$resultado= mysql_query($sql); . _ o , .i . ,. .. ,
-1 1 (- k - ' r- .. .,_..._
nw.1-,
,ns,,,:.f!IOO'llorc!

Esta lista de resultados se guarda en una array ca... .. --

llamada $row y se lee con ayuda de un bucle,

... H "11
-
lnea a lnea. El bucle empieza con: En ese caso se enva el mensaje de felicitacin
while ($row = de cumpleaos al destinatario, con una copia a
mysql_fetch_assoc($resultado)) ti mismo (el remitente).
Para acceder a los distintos campos utilizamos
el nombre de cada campo como key de la arra
y. Es decir, recuperaremos la direccin de email
con $row I "Mail"], y la fecha de cumpleaos
con $row ["Cumpleaos"].

A continuacin, comprobamos si el campo


Mail tiene contenido:
if {lempty($row["Mail11])) {

Si no se ha introducido la direccin de email,


no tiene ningn sentido enviar un mensaje de
felicitacin.

Envo de e-mails
A continuacin entra en escena la funcin ex
plodei), ya que tenemos que extraer como m-
nimo el mes y el da de la fecha del cumplea
os en formato AAAAMMDD:
$cumple= explode("-", $row["'
Cumpleaos"]);
Esta funcin divide la fecha del campo Cum
pleaos con ayuda del signo de guin () en
ao, mes y da. El resultado se guarda como
array con una key numrica. As, podremos
acceder al da de la semana con $cumple [ "2 J, 11

y al mes con $cumple ["1"] etc.


A continuacin, realizamos una comparacin.
Coinciden el da de la semana y el mes?
Edita el cdigo PHP con tu editor: el texto del lioy es 27.ll4.200fi!
men Te tetci13rnos de lodo corazn por tu

pr--
saje se almacena en la variable $mailtext mrtJieoiios
y le deseamos toclO Jo me;ortanto en .. llida
Los saltos de lnea se convierten en saltos de
lnea en el email, por lo que dividir el texto en
prrafos es la mar de sencillo.
-
S1rta!rameflle -

Todos los que cumplan aos recibirn un mensaje


de felicitacin personalizado. Naturalmente,
puedes adaptar el texto del mensaje.

p
eJ 516,JJN:t: rlaipcwbJGN E ,_
INl'C fflVlceQ!chark,d@
Dlltr.: 18::3) Un par de lneas de cdigo ms abajo, se env
T' an los mensajes de correo electrnico con la
" funcin mail(), en conjuncin con una consulta
if. La primera consulta comprueba si se ha en
viado el mensaje de felicitacin. De ser as, se
62 Felicitacin de cumpleaos con cronjob
enviar el mensaje de confirmacin al remiten De esta forma, vers enseguida su telfono y
te. podrs llamarle. Con tantas atenciones, seguro
que tus amigos estarn encantados.
Naturalmente, tambin puedes utilizar este
Atencin! ... el mensaje de recordatorio te script para enviar mensajes de advertencia.
evitar posibles situaciones embarazosas. O puedes usarlo para distribuir boletines de
noticias. Basta con eliminar la consulta sobre
la fecha de cumpleaos. Lee el texto del bo
Ejercicios sobre el script de letn de forma dinmica desde un campo de
formulario e insrtalo en lugar del texto de
cumpleaos felicitacin.
Naturalmente, puedes seguir ampliando el
proyecto y adaptndolo a tus necesidades. En Ejercicio 3: ajustar el formulario
este sentido, te he preparado un par de ejerci Ajusta los documentos para introducir y mos
cios: trar los datos de forma que tengan en cuenta el
campo de cumpleaos y el nuevo campo adi
Ejercicio 1: completar un campo cional que has creado en el ejercicio l.
adicional Aviso: para estos tres ejercicios no ofrezco los
Crea un campo en la base de datos con infor archivos con la solucin, porque estoy conven
macin adicional, muy personal. Si existe, este cido de que no son nada complicados.
texto se leer de la base de datos y se agregar
al texto del email. De este modo, tus emails
sern ms autnticos, porque los destinatarios
recibirn informacin muy personal.

Ejercicio 2: "ampliar" el mensaje de


recordatorio
Ampla el texto del mensaje de recordatorio
con el nmero de telfono del contacto. Inserta
el nmero al principio del mensaje de recorda
torio.
Proyecto: libro de visitas con fotos 63

El proyecto: libro de visitas, CMS


o fotoblog?
Ha llegado la hora de presentar la perla del cua una fotografa, cuya anchura no debe superar
derno: el libro de visitas versin "deluxe". Con los 200 pxeles.
un cmodo sistema de introduccin de datos,
carga de archlvos de imagen y presentacin de Si se carga la foto correctamente, el script guarda
las entradas por pginas. la nueva entrada en la tabla de la base de datos,
publicndola en el libro de visitas. Si el usuario
Adems, incorpora un rea de administracin no publica una foto, no se crear la entrada.
para eliminar las entradas no desedas.
Para lograr que todo sea lo ms claro posible
He intentado hacer que el script sea lo ms y facilitar la estructura, suelo trabajar con par
universal posible para poder transformarlo tes modulares, es decir, archivos separados.
fcilmente en un lbum de fotos o en un mini De este modo te ser ms sencillo adaptar este
sistema de gestin de contenidos (Content proyecto a tus necesidades.
ManagementSystem, CMS). Tambin es muy
fcil protegerlo mediante contrasea. Como veremos, esta ventaja de externalizarlo
todo empieza por el propio diseo de la pgina.
Ests listo? En ese caso, antes de nada te pre
sentar tu nuevo libro de visitas con fotos:
Formato con archivo CSS
Del diseo del libro de visitas se encarga el ar
Mi libro de visitas chivo CSS gb_tabla.css. Por motivos de espacio,
- - - -,,
( l ( J
no copio aqu el cdigo fuente completo de di
cho archivo, pero puedes consultarlo tranquila

i1
mente abriendo los archlvos del suplemento. En
el archlvo CSS determino los tipos y tamaos de
fuente, los efectos de los vnculos y establezco
unas determinadas dimensiones para el conte
nido. Incluso las lneas verticales del margen iz-
. _, quierdo se crean mediante CSS .
_,,,u,J,--....._

1lKWl 1 l!IK'l!
Consejo: en el cuaderno Crea tu sitio web:
!
aprende HTML y CSS el autor David Bosman
te presenta todas las opciones de diseo y
formato que ofrece este fascinante lenguaje.

La primera entrada en el libro de visitas c.;1r CH fuente p&ril todo 11 doc.-nto ,


font-fillllly: verd1.n.,...,...,_1,
1telv1tiu., .,iertf;
El usuario ver una interfaz amigable, con todas 11u91n: Op;
bilCIUJ("DOJnd-t,ug1: url('1>W11low. 9lf');
1
las entradas introducidas en el libro de visitas. / Pirr&fOS, ubl.is, foreular1os il 10 xmtos
Las ltimas entradas aparecern arriba de todo, 10
p, dlv, uble, 11. for" (
font-s1u: tOpt;
y las ms antiguas sern accesibles a travs de u
u
J
enlaces. u
u
/ Color grh
h1 {
u fom.-f-'il)": ver . ..,.bl, itelYnk. un-nrif;
l color: sllver;
Al hacer clic en Introducir entrada se muestra un u J
formulario para introducir una nueva entrada.
El formulario permite introducir el nombre, la Formato con CSS: las reglas estn comentadas
direccin de correo electrnico, la pgina web y La ventaja que presenta este mdulo externo es
el texto del mensaje para el libro de visitas. que es muy fcil crear un diseo nico. Ajusta el
Adems, el usuario tiene que publicar tambin archlvo CSS a tus necesidades y tendrs un libro
de visitas completamente distinto.
64 Proyecto: libro de visitas con fotos
El mdulo del libro de visitas eliminar.inc.php
ministrador(= propietario del libro de
visitas) con ayuda de cookies.
Este archivo se encar-a-e-l-m_i_-,--
A continuacin, veamos cmo est estructurado s-<[ entradas no deseadas del libro de
nuestro sistema modular. He dividido cada par visi- tas.

te importante en un archivo separado. Tenemos En la carpeta librovisitas he creado una subcarpe


un archivo include para la introduccin de da ta especfica para guardar las imgenes carga
tos, otro para la administracin y otro para eli das, a la que he llamado img.
minar entradas. Crear los vnculos para pasar
las hojas mediante una funcin propia. Como
veremos, la instruccin include() nos ser de gran Variables de edit.inc.php
ayuda en este proyecto.
En total, el libro de visitas est formado por los Lo interesante de este ejemplo es el archivo de
siguientes archivos, todos en la misma carpeta, edicin central edit.inc.php. Me parece muy til
que en mi caso he llamado librovisitas. reunir todos los datos y variables de control im
portantes en un punto central.
Nombre archivo Descripcion
index.php Es el archivo principal. Es el archivo
Por tanto, aqu podemos establecer los datos de
que abre el usuario. acceso a MySQL o los datos de acceso al rea de
edit.inc.php Area de edicin en la que se controlan administracin.
todas las contrasef'las y configuraciones
de forma centralizada mediante varia- En este ejemplo, el archivo edit.inc.php se en
bles - tambin los datos de acceso a cuentra en la misma carpeta por pura como
MySQLI didad. En la prctica, podras guardarlo en la
runction.inc.php Contiene la(s) funcione(s), en este caso subcarpeta cgi-bin. En ese caso, ajusta la ruta
la funcin para pasarpginas.
de acceso include del archivo index.php, lnea
acceso.inc.php Este archivo controla el acceso al ser-
vidor MySQL y toma las variables de
7, as como en el archivo de instalacin adi
edit.inc.php. cional seiup.php, linea 11.
ntroduccion.inc.php Aqul se genera el formulario para intro-
:ducir los datos. Este es el cdigo de mi archivo edit.inc.php, he
admin.inc.php Este archivo controla el acceso del ad- comentado todas las variables:
-

<?php
$dbname "sql_profi"; // Nombre de la base de datos
$dbhost "localhost"; // Host de la base de datos, casi siempre localhost (excepto l&l)
$dbuser "root"; // Nombre de usuario para MySQL
$dbpassword .. ""; // Contrasea para MySQL

$user = "admin"; // Nombre de usuario del administrador


$passwo..r. d "' "test"; / / Contrasea del administrador

$ancho= 200; // Anchura mxima de los grficos


$step = 2; // Cuntas entradas se pueden, mostrar al mismo tiempo?
?,

La tabla gb_tabla Name VARCHAR(40),


Mail VARCHAR(50),
Homepage VARCHAR(50),
Naturalmente, todava nos falta crear la tabla de Imagen VARCHAR(35),
la base de datos, que en nuestro caso se llamar Fecha VARCHAR(30),
gb_tabla. Puedes extraer los campos, nombres de Entrada TEXT
campo y su significado analizando el cdigo: 1
CREATE TABLE gb_tabla{ Si no te apetece crear la tabla a mano, te he pre
id INT NOT NULL AUTO_INCREMENT (;P parado un archivo llamado setup.php. Antes de
PRIMARY KEY, nada, asegrate de configurar correctamente las
Proyecto: libro de visitas con fotos 65
primeras 4 variables de edit.inc.php. A continua Abajo he copiado el cdigo fuente completo del
cin, ejecuta el archivo setup.php abrindolo en el archivo principal del proyecto, index.php. Des
navegador. De esta forma, se crear automti pus te explicar paso a paso cmo funciona.
camente la tabla gb_tabla.

Recuerda que debes ejecutar el comando


chmod 777 para permitir la lectura y escritura
en la subcarpeta img.

Cdigo fuente completo de index.php


1 <?php
2 $start = O; / / Establecer valor inicial { O = 1. filas)
3 $output = 11 n; / / Variable de salida/
4 if {isset($_GET['start']}) { // Modificar valor inicial
5 $start = $_GET (' start');
6
7 include("edit.inc.php");
8 include(11acceso.inc.php");
9 include("function.inc.php);
10 include("admin.inc.php");
11
12 ?>
13 < ! DOCTYPE HTML PUBLIC 11
/ /W3C/ /DTD HTML 4. O Transitional/ /EN">
14 <html>
15 chead
16 <title>Libro de visitas</title>
17 <meta httpequiv="contenttype11 cont enr e vc ext Zhcml charset=iso88591">
18 <link rel= "stylesheet 11 t.ype 1 text/css n href= 11gb_tabla. css" >
19 </head>
20 cbody
21 <a nameev t.opv s c y a
22 cd .v align="center">
23 <?php
24
25 echo "<div class='marco'>";
26 include (" introduccion. inc .phpv j :
27 include ("eliminar. inc. php") ;
28 echo "<hl>Mi libro de visitas</hl>
29 ed .v [ <a href=' $_SERVER [PHP_SELF) '>Home</a> 1
30 [ <a href='$_SERVER[PHP_SELF]?entrada=true'>Introducir entrada</a>)
31 </div>";
32 $sqll = "SELECT * FROM gb_tabla";
33 $sql2 :e: nsELECT * FROM gb_tabla ORDER BY id DESC LIMIT $start, $step";
34 $resultl = mysql_query{$sqll);
35 $filas= mysql_num_rows($resultl);
36 $result2 = mysql_query{$sql2);
37 echo "<pcCarrt Ldad de entradas: $filas</p>\n";
38 // Inicio bucle while
39 while {$row = @mysql_fetch_assoc {$result2)) {
40 $Entrada nl2br {$row [' Entrada 1]);
41 $tamanyo = GetimageSize { 11 img/" . $row ['Imagen'] ) ;
42 $output .= "<h3>$row(Nombre] </h3>\n
43 cp s c .mq src=' img/$row [Imagen] ' $tamanyo [3] a.Lt; '$row [Nombre) '></p>
66 Proyecto: libro de visitas con fotos

44 <div>$Entrada</div>" . 11
<p>introducido por ebs s rov [Nombre} </b> el
45 <strong>$row [Fecha] </strong>";
46 if ( !empty($row[ 'Mail'])) {
47 $output .= "<div><strong>E-Mail</strong>: $row[Mail]</div>11;
48
49 if (!empty($row[1Homepage'])l {
50 $output . "" 11 <div><Strong>Home</strong>: $row [Homepage] </div>";
51
52 if (isset($_COOKIE[1conectar']}) {
53 $output . ""' "ed .v [ <a href=' $_SERVER [PHP_SELF] ?eliminar:&
true&id=$row[id]&step=$step&start=$start'>Eliminar fila</a>} -
54 [ <a href='$ SERVER[PHP SELF]?desconectar=true&step=&
$step&start=$start >Desconectar</a> J </div>";
SS
56 $output '"' "<P class='linea'>&nbsp;</p>\n";
57 // fin de while
58 $output . = "<P> [ <a href= 1 #top' >arriba</a> ] </p>";
59 echo navi_page($start, $step, $filas);
60 echo $output;
61
62 mysql_close();
63
64 echo "<form action='$_SERVER[PHP_SELF]?step:::$step&start=$start' method:::'post'>";
65
66 ?>
67 <input t.ypeev eubm.t;" va Lueen eqt; r " c Las aevm.n i "
68 <input type="text" name="logname" c Laaeevm. n ." >
69 <input type=password" name="logpw" c Las s e vrn.n ,">
70 </form>
71 </div>
72 </div>
73 </body>
74 </html>

Vincular los datos de acceso Cdigo SQL para datos


A primera vista, debemos fijarnos en las lneas 7 Detengmonos un momento en la lnea 32. Aqu
y 8, donde se vinculan los datos de acceso. empiezan los "preparativos" para mostrar las
Adems, el archivo acceso.inc.php de la lnea 8 entradas del libro de visitas. La lnea 32 selec
utiliza a su vez algunas variables de edii.inc.php, ciona todos los registros de la tabla, lo que per
A continuacin, copio rpidamente el cdigo de mite determinar la cantidad total de entradas y
acceso.inc.php. Este archivo se encarga de la co presentar este dato en la lnea 37.
nexin con el servidor de la base de datos y de . Qu hace la consulta de la lnea 33? Ordena las
seleccionar la base de datos deseada. entradas de forma descendente por id, de modo
<?php que las ltimas entradas aparecen las primeras
& de la pgina.

I
@mysql_connect ( "$dbhost", "$dbuser",
"$dbpassword")
or die ( "Conexin con el servidor & Adems, utilizo tambin UMIT.
no establecida."};
@mysql_select_db("$dbname") or & Limito la cantidad de datos que se muestran, un
die ("Acceso a la base de datos & detalle importante para nuestra funcin para
fallido.") ; "pasar pginas". He inicializado la variable
$start en la lnea 2 con O, por lo que inicialmente
De momento, no es necesario que te fijes en las la cantidad de entradas es O. De la variable $step
siguientes lneas. me he ocupado en el archivo edit.inc.php. Si la
has establecido como yo en 2, se mostrarn dos
Proyecto: libro de visitas con fotos 67
entradas seguidas. Prubalo, cambia el valor de Las lineas 5255 estn reservadas al rea de ad
$step en el archivo edit.inc.php. ministracin. Solamente se mostrarn si el pro
pietario del libro de visitas se conecta con el
nombre de usuario y la contrasea correctas, y
Mostrar los datos se crea una cookie. Despus volveremos sobre
ello.
La forma de mostrar y presentar los datos no
debera suponer ningn misterio. De ello me he $output y navi_page()
ocupado entre las lineas 38 y 52.
Te has fijado en que almaceno toda la string de
Mediante la funcin mysql_fetch_assoc() recu los registros en la variable $output?
pero las entradas de la tabla y las presento con
HTML. He inicializado la variable en la linea 3. Sin em
bargo, no guardo datos en ella hasta la linea 42.
La entrada del libro de visitas propiamente Y es en la lnea 60 cuando muestro su contenido
dicha se somete en la linea. 40 a un tratamien utilizando echo. De este modo puedoe mostrar
to especial con nl2br(). Esta funcin, que ya los vnculos para "hojear" el contenido encima
presentamos en el cuaderno anterior, trans de las entradas propiamente dichas, ya que apa
recen en la linea 59.
forma los saltos de linea en la etiqueta cbr />.

La imagen se muestra en la linea 43, despus de


I La linea 59 llama a la funcin navi_page().
determinar en la linea 41 sus dimensiones. (Si no Ha llegado el momento de ocupamos de esta
deseas incluir la imagen, slo tienes que elimi nar funcin, de sus argumentos y, en consecuencia,
estas dos filas). De la linea 46 a la 51 nos del archivo Junction.inc.php.
ocupamos de presentar la direccin de correo
electrnico y la pgina web. Dado que considero Cdigo fuente de function.inc.php Observa el
estos dos campos como opcionales, compruebo cdigo fuente del archivo [une tion.inc.php, que
antes de mostrarlos si estn vacos. Lgicamen he vinculado a la pgina princi pal (index.php) en
te, slo deben mostrarse si no estn vacos. la linea 9:

<?php
function navi_page($start, $step, $filas)
{
$startl $start + $step;
$start2 $start - $step;
$output "11;
if {$startl e $filas) {//Inicio if
$output .= " [ ca href=\11$_SERVER[PHP_SELF] ?start=$startl\">&lt;&lt; cP
Entradas anterioresc/a> ] ";
}
if
($start2 > O) {
$output .= 11 [ ca href=\"$_SERVER[PHP_SELF] ?start=$start2\11>Entradas <!)
ms recientes &gt;&gt;</a> ] \n";
} // if-Ende '
$output = "<p>$output</p>";
return $output;

,,
La funcin recibe tres parmetros: el valor ini Cantidad de ent:Jradas: S
cial, la cantidad de registros a mostrar y el total
[ << Entradas anterior-es ] [ Entradas ms reoen>>]
de registros. La funcin analiza estos tres datos
y, en funcin del resultado, devuelve el texto En
tradas anteriores, Entradas ms recientes o ambas Si hay varias entradas, podemos "hojear" hacia ade
cosas juntas. lante y hacia atrs.
68 Proyecto: libro de visitas con fotos
Para ello se utilizan clculos y comparaciones.
La funcin no es complicada, estoy seguro de Introducir una entrada
que podrs aclararte con la programacin de la
misma. Hasta aqu todo suena bien, pero ... cmo se
puede introducir una entrada al libro de visitas?
Lo importante es que los valores iniciales Utilizando un principio muy parecido. Observa
(start=) se transmiten al vnculo en forma de la lnea 30 de index.php. Tambin he agregado un
parmetro. parmetro a la URL del vnculo, en este caso:
?entrada=true
Si hojeamos una pgina hacia atrs, la funcin
puede agregar, por ejemplo, start=4 al vnculo. Est establecida la variable $_GET['entrada'J?
[ Entradas De ser as, se visualiza el formulario y se pueden
recibir los datos.
Y eso ocurre precisamente en introduc
cion.inc.php, Ya he vinculado este archivo en la
lnea 26, debajo de la lnea del diu:
El agregado a la URL se aprecia en la lnea de estado
echo "<div class=='marco'>n;
La direccin completa sera: include("introduccion.inc.php11);
index.php?start4
Por qu? De este modo, logro que todo el for
mulario quede dentro del diseo especificado
La variable $_GET['start'] para dio clnsse'marco', ya que el contenedor
Aqu entran en juego las lneas 4-6 de index.php, div asegura una anchura exacta de 700 pxeles.
donde el script comprueba si el parmetro de la Empieza en la lnea 25.
URL llamado start existe. Existe la variable
$_GET['start']? Tiene el valor 4? Fantstico! Se A continuacin, veamos el cdigo fuente com
guardar el valor en $start y en lugar de O pleto del archivo introduccion.inc.php:
habremos cambiado dinmicamente el valor de
start a 4.

El formulario: cdigo fuente de introduccion.inc.php


1 c Ppbp
2 // Creacin del formulario:
3 if (isset($_GET['entrada']))
4 echo <<<FORMULARIO
5 <h2>Identiffcate y carga tu foto.</h2>
6 <p>Por favor, utiliza el formato GIF o JPG y respeta la <br>
7 <b>anchura mxima</b> de <strong>{$ancho}</strong> pixeles.<br>
8 Con respecto al tamao de la imagen, recuerda: <Strong><b>small</b> is &
beautiful</strong>!</p>
9 <form action="{$_SERVER('PHP_SELF'] }" method="post" enctype=multipart/form-data">
10 Nombre y apellido:<br>
11 <input t ypee v t.ext;" nameev Nomb.rev s cbz
12 Direccin de e-mail:<br>
13 <input trypeev t ext;" name::"Mail11><br>
14 Homepage:<br>
15 <input type=11text11 name=11Homepage"><br>
16 Imagen:<br>
17 <input type::11file11 name:r"archivo"><br>
18 Escribir texto:<br>
19 <textarea cols="6511 rows="l5" wrap=11soft" name="Entrada">
20 </textarea><br>
21 <input t ypevvaubm.t " nameev subm.t " value="Introducir entrada --&gt; ">
Proyecto: libro de visitas con fotos 69

22 Paciencia al cargar!
23 </form>
24 <p>( <a href=index.php11>Cancelar entrada</a> J</p>
25 FORMULARIO;
26 }
27 if ( !empty($_POST ['Nombre']) && !empty($_POST ['Entrada']))
28 // Cargar foto, despus introducir datos
29 $upload = false;
30 if (isset($_FILES['archivo']) && $_FILES['archivo] ['size') > O) {
31 $nombretemp = $_FILES['archivo'] ['tmp_name');
32 $nombrearchivo = $_FILES['archivo'] ['name'];
33 $tamanyoarchivo = $_FILES('archivo'] ['size'];
34 $tipoarchivo = GetimageSize($nombretemp);
35 if 1$tipoarchivo[2] == 1 11 $tipoarchivo[2] == 2) { // GIF o JPG?
36 $extension = {$tipoarchivo[2] == 1 ? "gif" : "jpg");
37 $nuevonombre = time () . '". $extension 11;
38 $anchoimagen = $tipoarchivo(O];
39 if ($anchoimagen <= $ancho) { // Imagen demasiado ancha?
40 if (move_uploaded_file($nombretemp, "img/11 $nuevonombre))
41 chmod("img/11 $nuevonombre, 0666);
42 echo "<h2>Mensaje de aviso para la carga:</h2>
43 <p>El archivo se ha cargado <b>con xito</b>.<br>
44 Tamao de archivo: <b>$tamanyoarchivo</b> bytes;<br>
45 Antiguo nombre de imagen: <b>$nombrearchivo</b><br>
46 Nuevo nombre de imagen: <b>$nuevonombre</b><br>";
47 $upload = true;
48 else {
49 echo "<h2>No ha funcionado.</h2>
50 <p>No se ha podido cargar el archivo.</p>";
51
52 else
53 echo "<h2>Atencin:</h2>
54 <p>El archivo tiene una anchura superior a <b>$ancho pxeles</b> y
55 es demasiado ancho.</P><form><input type=1button value='Volver'
56 onclick=' javascript: history .back () ></form> 11;
57
58 else
59 echo 11<h2>Atencin:</h2>
60 <P><b>No</b> es un archivo GIF
61 o JPG vlido.</P><form><input type='button' value='Volver1
62 onclick=' javascript :history .back () '></form>";
63
64 else
65 echo "<h2>Falta algo.</h2>
66 <p>Indica un archivo <b>de imagen</b>.</P>
67 <form><input type='button' value='Volver'
68 onclick=' javascript: history. back () ></form> 11
;

69
70 if ($upload) {
71 $fecha= dat.e Lvd m.Y, H:i") . "horas";
i

72 $Nombre= strip_tags($_POST('Nombre']);
73 $Mail = strip_tags($_POST[1Mail']);
74 $Homepage = strip_tags($_POST['Homepage']);
75 $Entrada= strip_tags{$_POST['Entrada']); $Mail 1
,

76 $sql :: "INSERT INTO gb_tabla " . "VALUES ( 1 ',


1
$Nombre 1
,

77 '$Homepage', '$nuevonombre', '$fecha', '$Entrada') 11


;
70 Proyecto: libro de visitas con fotos
78 if (mysql_query($sql) 1 {
79
echo "<p>Se ha podido introducir los datos en la base de datos.</p>";
80 else {
81
echo 11 <P><b>NO</b> se ha podido introducir los datos en la base de&
datos. </p>";
82
83
echo "<h3>[ <a href='$_SERVER(PHP_SELF]?step,,.$step&start=$start'>;No te cP
olvides de desconectarte!</a> ]</h3>
84
<P>
85 <script language='JavaScript' type='text/javascript'>
86 document.write(' ... desconexin automtica en 8 segundos.);
87
setTimeout ( 'self. location=\ $_SERVER [PHP_SELF] ?start=$start&step=$step\ 11
11
' , cP
8000)
88 </script>
89 </p>";
90
91 else if (isset($_POST(1submit1])) {

92 echo "<h2>Todavia falta algo!</h2>


93 <p>Deben rellenarse <b>todosc:/b> los campos.</p>
94 c:form><input type-1button1 value:1Volver1
95 onclick='javascript:history.back() '></form>11;
96
97
98 ?>

Te parece complicado? Qu va. Ya conoces la campos Nombre y Entrada. De ser as, se ejecuta
mayora de cosas que aparecen de ejemplos an el script para cargar la imagen, y despus el
teriores. script para introducir los datos en la base de da
Lo primero que se hace es crear el formulario. tos.

En la lnea 27 compruebo mediante una com Todo este bloque se alarga hasta la lnea 90.
probacin rudimentaria si se han rellenado los

Identifcate y carga tu foto.


Por favor, utiliza el fonnato GIF o JPG y respeta la
anchura mxima de 200 pfxeles.
Con respecto al tamano de la imagen, recuerda: small Is beautffull

Nombre y apell.do:
1
Direccin de e-mail:

Homepage:
Imagen: Examinar..

Escribir texto:

Para el libro de visitas se exige tambin una foto.


Proyecto: libro de visitas con fotos 71
De lo contrario, el script salta a la condicin else Por ese motivo establezco la variable $upload de
if de la lnea 91, donde compruebo si existe la la lnea 29 en false, porque quiero comprobar si
variable $_POST['submit'J. Solamente ser as si se ha logrado cargar el archivo. Solamente se in
se ha enviado el formulario. Las lneas siguien troducir la entrada en la base de datos si el pro
tes muestran una advertencia y ofrecen un botn ceso de carga de la imagen ha funcionado.
para que el usuario pueda volver atrs.
El siguiente prrafo coincide prcticamente en
Uso de JavaScript su totalidad con el sistema de carga de imgenes
Corno se puede ver, para el botn de retroceso que hemos visto al principio del cuaderno.Con
de las lneas 9495 he utilizado JavaScript; tam sulta unas pginas hacia atrs; a partir de la p
bin encontrars esta tcnica en otros sitios. gina 18 te explico concretamente cmo funciona.
Para evitar posibles problemas, en la lnea 41
La instruccin onclick= 'javascript:history.back()' se ejecuto el comando chmod para la carpeta img.
encarga de dar el salto hacia atrs. Recuerda que ya hemos hablado de ello en la
Sin embargo, por lo general no suelo trabajar con pgina 23.
JavaScript, porque cada vez son ms los usuarios Cuando finaliza la carga, el script cambia el va
que desactivan este lenguaje en su na vegador. lor de la variable $upload de la lnea 30 a true,
De ser as, lo nico que pasar es que el botn concretamente en la lnea 47.
"volver" no funcionar.
En ese caso, el usuario tendr que retroceder una Escribir texto en la base de datos
pgina utilizando el botn de navegacin del En la lnea 71 se comprueba si se ha cargado co
propio navegador. rrectamente la imagen. Si la respuesta es afirma
tiva, se escribe el texto de los campos del formu
Informacin para usuarios que desactiven lario en la base de datos.
JavaScript
Proteccin contra skriptkiddies: strip_tags()
Si quieres ofrecer un trato mejor a los usuarios
que hayan desactivado JavaScript, puedes He aprovechado tambin para protegerme
ampliar el cdigo con un par de etiquetas frente a skrptkddes, es decir, amateurs que
<noscripl></noscript>. El contenido entre di intentan una y otra vez hacer mucho dao
chas etiquetas solamente se mostrar para con pocos conocimientos. Al posible cdigo
aquellos usuarios que hayan desactivado Ja HIML, JavaScript o CSS no se le ha perdido
vaScript. Aprovecha para aadir el siguiente nada por nuestra base de datos. Por eso lm
cdigo en todos los puntos donde hayas utili pio el contenido de todos los campos del for
zado comandos "volver" creados con JavaS mulario en las lneas 7275, utilizando la fun-
cript: cin strip_tags().
eclw <noscript>Utiliza el botn Atrs del
nave gador para volver a la pgina ante rior. Como se puede ver, lo que he hecho es convertir
</noscript> "; las variables $_POST en variables ms cortas.
$_POST['Nombre'J se convierte en $Nombre,
Yo no he incluido este cdigo adicional en mi $_POST['Mai/'J en $Mail, etc. etc.
ejemplo por motivos de espacio. En la lnea 71 determino la fecha actual y la
hora.
Sistema para cargar imgenes A diferencia del libro de visitas del cuaderno an
Si las variables $_POST['Nombre'] y terior, en este caso utilizo tambin la hora.
$_POST['Entrada'J no estaban vacas, significa
que el usuario ha introducido su nombre y un
texto para la entrada del libro de visitas. En ese Volver al mismo sitio
caso, en la lnea 2728 empieza la zona dedicada
a la carga de la imagen. Partiremos de la premisa Y qu ocurre en la lnea 83? Por qu le indico
de que no funciona siempre es bueno presupo al usuario que no se olvide de desconectarse? Lo
ner que no funcionar ;) que me interesa es que el usuario no siga toque
teando el formulario; por ejemplo, podra hacer
clic en el botn Actualizar del navegador o vol
ver una pgina hacia atrs y despus otra vez
hacia adelante.
72 Proyecto: libro de visitas con fotos
Desconectarse significa desconectarse, sin La confianza est muy bien, pero el control es
mejor. As, si el usuario no hace clic en el vnculo
concesiones.
No te olvides de desconectarte! tras 8 segundos, se
ejecuta automticamente el cdigo JavaScript de
Observa el interesante vnculo que he incluido la lnea 8588. La pgina se llama a s misma una
en esta lnea de cdigo: vez transcurridos 8. En este caso tambin se
$_SERVER[PHP_SELFJ?step=$step&start=$start transmiten los parmetros step y start.
Es un buen truco: transmito los parmetros para Proteccin contra entradas duplicadas
nuestra instruccin LIMIT. No slo indico el va
lor de step ( = la cantidad de filas que se deben Para protegernos frente a posibles entradas
mostrar al mismo tiempo), sino tambin el valor duplicadas, tambin es necesario usar la tc
de start. As, el script puede mostrar la pgina nica que hemos visto en la pgina 53 con un
exacta desde la que el usuario haba llamado al "unique index". Te recomiendo que asignes
formulario para crear una nueva entrada. este tipo de ndice a los campos Nombre, Mnil
Si no hubiera incluido estos parmetros, tras la y Entrada. Al fin y al cabo, es muy, muy im-
desconexin el usuario siempre terminara en la probable que dos usuarios tengan el mismo
pgina principal. nombre, la misma direccin de correo electr
nico y escriban exactamente el mismo texto en
la base de datos.
Mensaje de aviso pan1 la carga:
a arctwo .. M c..-pda coa b;tw.
T...-lo t ilf'Ctwo: 1:4SM bytu:
AnbgUO . '
taNa.glf
- narrtn 11' ' 1146219857.9"
S. NI pocillo flb los tos en la N5e d9 <ba.,

l lNP te olvides de desroncctortcl J


.. .dueonuilln autic: en

Mensajes de estado y de confirmacin para el usuario.


rea de administracin

73

Administracin: eliminacin de datos


no deseados
Para terminar, veremos una ltima sofisticacin index.inc.php a propsito, concretamente en la l-
del script del libro de visitas. Se trata del rea de nea 10, porque, en caso de que el usuario se
adnnistracin, pensada para poder eliminar en identifique correctamente, se crea una cookie.
tradas no deseadas.
Observa nuevamente el cdigo fuente de in Las cookies deben transmitirse siempre en el
dex.php, las lneas 6470. Correcto, aqu es donde header de la pgina, antes de la etiqueta
hemos ocultado el formulario de conexin para <html, y de la declaracin del tipo de docu

[
l
I

el adnnistrador. mento (DTD).

Cdigo fuente de
l!!!m

admin.inc.php
, ..Y.lm,n

:6
Este es el cdigo fuente que crea la cookie; se tra
El formulario para el administrador est ta del cdigo del archivo admin.inc.php:
bastante camuflado
Tras introducir el nombre del administrador y la
contrasea (ambos se han determinado en el ar
chivo edit.inc.php) se abre el archivo ad
mininc.php, Lo he vinculado al principio de

<?php
if (!empty($_POST['lognameJ) && !empty($_POST['logpw'])) {
if ($_POST['logname1J == $user && $_POST['logpw'] == $password)
setcookie ( conect.arv, 11
true") ;

echo 11
<script language=1javascript' type='text/javascript'>
self.location=\11$_SERVER[PHP_SELF]?start=$start&step=$step\11
</script>";

if (isset($_GET['desconectar']))
setcookie ( conect arv , 1111, 3600);
echo "<script language='javascript' type='text/javascript1>
self.location=\11$_SERVER[PHP_SELF]?start=$start&step=$step\11
</script>11;

?>

Si el nombre de usuario ($_POST['logname']) y Mostrar un vnculo de eliminacin


la contrasea ($_POST['logpw']) no estn vacos Volvamos a index.php, concretamente al prrafo
y coinciden con los valores de las variables $user de la lnea 5255. Aqu comprobamos si existe la
y $password, se crea una cookie llamada conectar cookie.
cuyo valor es true. Se trata de una cookie de se
sin, que desaparecer en cuanto el usuario cie if (isset($_COOKIE['conectar'])) {
rre la ventana del navegador. En caso afirmativo, el script mostrar unos vn-
A continuacin, una rutina en JavaScript se en culso adicionales para eliminar entradas y para
carga de que la pgina se llame a s misma au desconectarse.
tomticamente. La cookie solamente estar lista
una vez que se recargue la pgina.
74 rea de administracin
Qu ocurre al desconectarse?
Observa primero el vnculo para desconectarse Eliminar una entrada:
de la lnea 54. Comprobars que aadimos un
parmetro a la URL llamado desconeciaretrue: eliminar.inc.php
$_SERVER [PHP_SELF] ?desconectar-true&...
Y si hacemos clic en el vnculo Eliminar fila? En
Este parmetro se analiza tambin en ese caso, se transmiten los parmetros elimi /
admin.inc.php, concretamente en el ltimo if. Si la naretrue e id=n" de fila. Estos datos se envan al
comprobacin es positiva, se vuelve a crear la script de eliminar.inc.php:
cookie, pero esta vez con una fecha de caduci dad
negativa.

El resultado es que se elimina la cookie exis


tente. Hey. yo no t:aogo fotw- au1Mr11

introducdo por S.ndra Marttnez arn :J&.04.2006, 12:.1.S bore

Compralo con el ejemplo sobre cookies que E-llllit: ..wd'4w.es


{ ) - [ f>MctlnKtar]
apareca en el cuaderno anterior.

Gracias al id podemos reconocer la fila de datos de


la tabla.

<?php
)) {
if (isset($_GET['eliminar']) && isset($_COOKIE[1conectar1 }
1 11
$sql3 = SELECT Imagen FROM gb_tabla WHERE id= 1 $_GET [id]
11
;
$result3 = mysql_query($sql3);
$row = mysql_fetch_assoc($result3);
$sql4 = "DELETE FROM gb_tabla WHERE id='$_GET[id] '";
if (mysql_query($sql4)) {
echo 11
<h3>Actualizacin c:strong>satisfactoria</strong>,
fila $_GET[id] eliminada.</h3>11 ;
if ( !empty($row l t Jmaqen t L) ) {
if (unlink ( 11 img/$row [Imagen] 11)
)

echo "<P>El archivo de imagen relacionado


<strong>$row[Imagen]</strong>
ha sido eliminado. </p>11;

else
echo 11<h3>Actualizaci6n <b>no</b> satisfactoria.</h3>11 ;
echo 11{ <a href=1$_SERVER(PHP_SELF]?step=$step&start=$start1>Todo correcto.</a>
] 11 ;

Puedes deducir por ti mismo cmo funciona A continuacin, selecciono la fila de datos de
este script? En primer lugar comprobamos por seada valindome del id de la base de datos, y
seguridad si todava existe una cookie de co determino el nombre de la imagen.
nexin.
En otra consulta SQL elimino toda la fila de da
Sera fatal si la propia existencia del parme tos. Si se logra eliminar correctamente, se
tro eliminar permitiese que se eliminasen da muestra un mensaje de confirmacin. Mi script
tos. intenta tambin eliminar el archivo de imagen
en caso de que exista.
rea de administracin 75

I La funcin unlink() elimina un archivo.


En ese caso, tambin muestro un mensaje de
confirmacin. Puedo hacerlo gracias al hecho /
de que la mayora de funciones devuelven true
o false dependiendo de si tienen xito o no.
Aprovecha la funcionalidad que brindan estos
valores.

Ejercicios para el fotoblog


Ejercicio 1: uso como fotoblog
Es posible adaptar el script para usarlo corno
weblog o corno fotoblog. Cmbialo segn de
sees. Solicita una contrasea en el formulario
para introducir datos a fin de que cualquiera
no pueda crear nuevas entradas.

Ejercicio 2: website y e-mail como


vnculo
Modifica el script de forma que se muestren el
sitio web y la direccin de correo corno hiper
vnculos.

Ejercicio 3: funcin para "hojear"


mejorada
Intenta mejorar la funcin para hojear las en
tradas de forma que tambin se muestre la can
tidad de pginas.
[ ) [ 91'.)) [ = l [ 2i:1li) [=JI ilc!Jll [)
Cantidad de entradas: 50

Todava mejor: un sistema para hojear entradas "de


luxe"
Para ello, tendrs que editar la funcin na
vi_page() de function.inc.php. Este ejercicio es
bastante complicado.
Aviso: no proporciono la solucin a estos ejer
cicios en el suplemento. Lo que cuenta es tu so
lucin.
ndice de palabras clave

ndice de palabras clave


$_COOKIE,8 Crear una tabla de Formulario de Normalizacin, 39
$_FILES, 20 direcciones, 30 introduccin para NOTNULL,29
$_GET, 7 CREATE TABLE, 29 libro de visitas, 70 Nueva columna en una
$_POST, 7 Cronjob, 59 Fotoblog, 63 tabla, 57
$_REQUEST, 8 CSS, 63 Funcin, 66 Nueva sintaxis de PHP,
$_SERVER,8 DATE,32,57 Funcin para hojear los 5
Activacin automtica DATETIME, 33 datos, 67 opendir(), 22
del script, 59 Definiciones de campos, Funciones or die(), 49
ADD COLUMN, 57 29 consultar en el manual Ordenar datos, 37
Administracin del DELETE,35 de PHP, 19 ORDERBY,37
libro de visitas, 73 Descarga de los nombres, 16
Ahorrarse el signo propias, 16 Parmetros de la URL,
escape, 10 archivos de ejemplo, sintaxis, 16 71
8 PHP4.2,5
lbum de fotos, 18 variables en funciones,
Determinar la cantidad 17 PHP5, 7
Almacenamiento de campos, 47 Guardar cdigo de phpinfof), 5
externo de variables, Determinar la cantidad forma externa, 13 PHPmyAdmin
64 de filas, 47 Heredoc, acceso a en las empresas de
ALTER TABLE, 57 DOUBLE,32 variables, 11 hosting, 26
Ampliar una tabla con Dreamhost, 26 interfaz para MySQL, 25
Identificador de Proteccin contra
una columna, 57 echo ms cmodo, 1 O conexin, 44
Anlisis de formularios Ejercicios sobre el reload, 53
include), 13, 14
segn la nueva acceso a bases de ,eaddir(), 22
INSERT INTO, 34, 52
sintaxis, 6 datos con PHP, 56 register_globals, 5
INT, 29, 32
AND y OR en SQL, 37 Ejercicios sobre el CMS, register_globals en off, 7
Introduccin, 3
Arrays con llaves, 9 75 Relacin, 39
Introducir datos, 30
Arrays sin comillas, 9 Ejercicios sobre el script Seguridad con la nueva
Introducir datos con
AUTO_INCREMENT, de felicitacin, 62 sintaxis, 7
SQL,34
29 Ejercicios sobre Seguridad, consejos y
lntrod ucir una entrada
Autorizar una carpeta, funciones, 17 trucos, 15
en el libro de visitas,
22 Ejercicios sobre la carga Seleccionar tabla, 44
68
Base de datos como de archivos, 23 Sintaxis heredoc, 10
JavaScript y PHP, 70
Cambiar de valor bruto sintaxis, 8 prctica, 19
Leer una carpeta, 22
a neto, 17 Ejercicios sobre la SMALLINT, 32
LEFT JOIN, 41
Campo clave, 29 proteccin con SQLDump, 55
Libro de visitas, 63
Campo de consulta, 51 contrasea, 15 strip_tags(), 71
LIKE,37
Carga de archivos, 18 Ejercicios sobre SQL, 41 Subdominios, 26
LJMIT, 37, 66
Carga de imgenes, 71 Eliminacin de entradas switch(), 15
Lista de direcciones, 28
Cargar archivos, 18 no deseadas en el Tablas, 28
Manual de PHP, 19
CHAR,32 libro de visitas, 73 Tamao mximo de
Mostrar campos, 36
CHMOD 777, 23 Eliminar datos, 35 archivos cargados, 21
Mostrar datos con PHP
Clusula WHERE, 36 Eliminar tags HTML, 71 TEXT,29,32
como tabla, 46
Clave primaria, 29 Eliminar un archivo, 74 TIMESTAMP, 33
Mostrar datos del libro
CMS,63 Encontrar errores, 11 Tipos de datos, 29
de visitas, 67
Consu1tar la contrasea, Enviar felicitaciones de Tipos de datos, los ms
Mostrar filas de datos, importantes, 32
13 cumpleaos, 57 36
Control de errores en el Estructura modular, 64 Trucos de PHP, 9
Mostrar una tabla como
acceso a la base de Evitar duplicados, 53 UNJQUE INDEX, 53
datos, 49 HTML,43 unlink(), 74
Evitar entradas move_uploaded_file(), UPDATE,34
Cookie para conectarse, duplicadas, 72 21
73 Evitar los mensajes de Uso de emails, 61
MySQL4,55
formuJario, 51
55 Filtrar, 36 mysql_close(), 45
Copia de seguridad de FLOAT,32 VARCHAR,32
bases de datos, 55 mysql_fetch_assocQ, 44 Vincular tablas con
Formato de fecha, 57 mysql_field_name(), 47
Crear una base de Formulario de carga de JOIN,39
datos, mysql_num_fields(), 47 XAMPP,4
Crear una28tabla, 29 archivos, 20 mysql_num_rows(),
mysql_select_db(), 4447
Secretos de PHP y MySQL MEJOR AN: PRESENTAR CADENAS
BIENVENIDO AL MUNDO DE LOS DE DATOS EN UNA TABLA ........................ 46
SITIOS WEB DINMICOS ... 3
MS SEGURIDAD PARA LA CONEXIN MYSQL .. 49
LA NUEVA SINTAXIS DE PHP
DESDE LA VERSIN 4.1 4.2 ........ 5 INTRODUCCIN DE DATOS:
FORMULARIO CON CAMPO DE CONSULTA ... 51
TRUCOS DE NOTACIN QUE HACEN
LA VIDA MS FCIL CON PHP ...................... 9 CREAR COPIAS DE SEGURIDAD DE TABLAS
Y TRANSFERIRLAS A OTROS EQUIPOS ... 55
MS COMODIDAD Y SEGURIDAD:
SEPARAR CDIGO CON INCLUDE(} ................ 13 FELICITACIN DE CUMPLEAOS
MEDIANTE CRONJOB ...... , .. , , .... 57
ESCRIBIR FUNCIONES PROPIAS ............. 16
EL PROYECTO: LIBRO DE VISITAS,
LBUM DE FOTOS: CARGA DE
CMS O FOTOBLOG? .............. 63
ARCHIVOS A UNA PGINA WEB ........... 18
ADMINISTRACIN: ELIMINACIN DE DATOS
COMODIDAD PARA MYSQL -
NO DESEADOS, .... , . , ..... , .. , ......... 73
LA INTERFAZ GRFICA PHPMYADMIN ... 25
Los MANUALES DE PC CUADERNOS ............... 76
BASES DE DATOS Y TABLAS:
UNA LIBRETA DE DIRECCIONES .... 28 VENTA AL NMERO ................... 77

PRINCIPALES TIPOS DE DATOS DE MYSQL ... 32 NDICE DE PALABRAS CLAVE ................... 79

INTRODUCCIN, ACTUALIZACIN
Y ELIMINACIN DE DATOS ................... 34
MOSTRAR, FILTRAR, ORDENAR
Y VINCULAR DATOS .......................... 36
CONSULTAR DOS TABLAS
SIMULTNEAMENTE CON JOIN .................. 39 ISBN 2-915605-46-7
QUE NO TE PASE NADA POR ALTO:
uso DE LEFT JOIN ................................. 41
PHP Y MYSQL: MOSTRAR LOS DATOS 111111111111
COMO PGINA HTML ......................... 43
9 782915 605464

S-ar putea să vă placă și