Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Curso:
PHP, MySQL y E-Commerce
Módulo:
“Diseño de aplicaciones con PHP y
MySQL”
Tutor: Ing. Oscar R. Espeche
Autor: Ing. Oscar R. Espeche
1
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Modulo 4:
Diseño de aplicaciones con PHP y MySQL
4-1 Libro de visitas con PHP y MySQL
En esta unidad veremos varias aplicaciones que conforman pequeños proyectos que considero
bastante útiles como ejemplo a la hora de elaborar sistemas más complejos.
Vamos a basar todo el trabajo en una misma página, que será la encargada de mostrar todas
las firmas de los visitantes y recoger los datos venidos por el formulario de participación para
introducirlos en la base de datos. Esto puede complicar un poco el código del ejercicio final
pero veremos el script por partes para que resulte sencillo. Ahora tan sólo tenemos que
entender su estructura general.
Explicación
La página del libro de visitas puede o no recibir datos por un formulario y dependiendo de ello,
debería hacer unas u otras acciones. Por tanto, lo primero que vamos a hacer es averiguar si
recibimos o no datos por el formulario.
Muestro las últimas 10 firmas del libro de visitas. Esto lo conseguiremos con un acceso a la
base de datos y un bucle que recorre los resultados de la búsqueda.
En el caso de que no se reciba datos, después de mostrar las últimas firmas, debemos saber si
existen o no más firmas en la base de datos para visualizar.
Por último, coloco el formulario de firma para que los visitantes puedan participar.
Esto quiere decir que el visitante ha rellenado el formulario de firma del libro y lo ha enviado.
Entonces debo registrar esta firma, aunque es muy importante que se realice una pequeña
comprobación y arreglo de los datos del formulario para evitar que un usuario malicioso
intente fastidiar el script insertando ciertos elementos susceptibles de arrojar errores como
etiquetas HTML o PHP. Entre las comprobaciones también nos aseguraremos, por ejemplo, de
que el usuario ha escrito algún dato en el formulario, pero veremos todas estas
comprobaciones más tarde.
Para el trabajo con el libro de visitas, como ya se ha apuntado, se requerirá el uso de una
base de datos. Bueno, en realidad lo que necesitaremos es contar con una tabla adicional para
la base de datos que ya contenga tu sitio web.
La tabla librovisitas_php
En este ejercicio deberemos crear una tabla con la información de las firmas. La llamaremos
librovisitas_php y contendrá los siguientes campos:
La tabla la podremos crear en nuestro servidor de bases de datos con la siguiente sentencia
Crearte Table:
Recordando la explicación general de este ejercicio, nos acordaremos de que la página del
libro de visitas tenía dos grandes bloques, que se decidían comprobando si se recibe o no algo
por el formulario. Para ello podemos utilizar un enunciado if como este:
if (!$HTTP_POST_VARS)
En caso de no recibir datos por el formulario este if se evaluaría con resultado positivo. Prestar
atención a la negación para entender la correcta evaluación del if.
En este capítulo vamos a relatar la parte del if en la que no se reciben datos por un
formulario, es decir, la evaluación positiva del if.
Autor: Ing. Oscar R. Espeche
5
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
En este caso, lo primero a realizar es la extracción de las últimas firmas grabadas en la base
de datos. Para ello debemos construir una sentencia SQL que seleccione de la base de datos
dichas firmas.
//si no recibo nada por el formulario de firma del libro, muestro las firmas del libro
//construyo la sentencia SQL
$ssql = "SELECT * FROM librovisitas_php";
//se mostrarán las últimas firmas, aunque habrá un enlace en la parte de abajo que se
podrá pulsar para ver más firmas
if (isset($_GET["vermas"]))
$ssql .= " where id_librovisitas_php<=" . $vermas;
Esta sentencia se construye en varias partes. Primero se crea la primera parte del select y
luego otras partes más complicadas de ver.
Será necesario un inciso para entender la parte en la que se evalúa si existe o no la variable
vermas, recibida por URL ($_GET["vermas"]). Esto viene porque en la parte de debajo de las
firmas, en caso de que existan más firmas de las que se hayan mostrado, se colocaría un
enlace para ver más firmas, que contendría una referencia a este propio libro de visitas con la
variable vermas igual al identificador de la próxima firma que haya que visualizar. Algo como
librovisitas/index.php?vermas=4
Si habíamos recibido la variable vermas, seleccionamos tan solo las firmas que tengan el
identificador menor o igual que el índice recibido en vermas.
Las firmas se deben ver en orden descendente, para que se muestren primero las últimas
firmas insertadas. Es lo que se indica en la parte que pone ORDER BY. Además se deben
seleccionar tan solo 10 firmas por página, aunque en la práctica seleccionaremos 11, aunque
la última no se mostrará, sólo se extrae para saber el índice que tiene y utilizarlo para
construir el enlace vermas, en caso de que existan otras firmas por visualizar.
Autor: Ing. Oscar R. Espeche
6
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Bucle While
Se realiza a continuación un bucle para recorrer los resultados. Es un sencillo recorrido por un
conjunto de resultados de una consulta a base de datos. Tiene la particularidad de que se
cuentan los resultados mostrados para, en caso de que se hayan mostrado ya 10, no seguir
mostrando más.
while (($damefila=mysql_fetch_object($resultid)) && ($num_filas<10))
{
?>
<table align="center" width="100%" cellspacing="2" cellpadding="0" border="0">
<tr>
<td valign="top" class=fuente8 colspan="2"><b>
<? //si el visitante no introdujo nombre, muestro como nombre "Anónimo"
if ($damefila->nombre == "-"){
echo "Anónimo";
}elseif ($damefila->email != "-") {
echo '<a href="mailto:' . $damefila->email . '">' . $damefila->nombre . '</a>';
}else{
echo $damefila->nombre;
}
?></b>:<br>
</td></tr>
<tr>
<td class=fuente8 valign="top">
<?echo strip_tags($damefila->comentario)?>
</td>
<td valign="top" align="right" nowrap class=fuente8>
Valoracion: <?echo $damefila->valoracion?>
</td>
</tr>
</table>
<br>
<?
$num_filas++;
} //termina el bucle while
Los resultados se muestran en una tabla, por eso puede quedar un poco embarullado este
código en medio de tantas etiquetas HTML, pero no reviste ninguna complicación especial.
//si quedan más valoraciones en el conjunto de resultados, muestro el enlace de "Ver más"
if ($damefila)
echo "<div align=center><b><a href=\"index.php?vermas=$damefila-
>id_librovisitas_php\">Ver más mensajes</a></b></div><br>";
include ("formul_mensaje.html");
El código del formulario para que los visitantes puedan incluir su firma en el libro de visitas es
el siguiente.
La otra parte del script del libro de visitas en PHP que nos queda por comentar contiene la
codificación de las acciones a tomar en caso de que sí se reciban datos del formulario. Dichas
acciones son básicamente comprobar si los datos son correctos y, si así es, insertar la
información en la base de datos.
Las comprobaciones sirven para asegurarnos que la información introducida va a ser siempre
válida, para que las firmas se muestren perfectamente. Determinadas informaciones podrían
dar lugar a errores al introducir la información en la base de datos o a la hora de mostrar las
firmas en la página.
Es muy importante borrar toda etiqueta HTML o PHP del texto de los campos introducidos por
el visitante. Si un visitante colocase este comentario:
Hola <b>Amigos</b>
Tendría como resultado que, al visualizar sui firma, se mostrase la palabra "Amigos" en
negrita. Esto no sería mucho problema, pero si se puede incluir una etiqueta así, también nos
podrían colar enlaces, imágenes o determinados elementos que pudieran descolocar la página,
cambiar nuestros estilos habituales o incluir scripts que pudieran molestar a otros visitantes o
a los administradores del sitio web.
Para no intentar introducir textos en la base de datos que en realidad no caben, recorto los
textos hasta su tamaño máximo.
También debemos comprobar que todos los campos introducidos no están vacíos, porque en
ese caso querría decir que el usuario está tratando de firmar con ningún dato sobre su nombre
o comentarios del web y no deseamos que eso ocurra.
<?
if (strlen($nombre)==0 and strlen($email)==0 and strlen($comentario)==0)
{
?>
<div align="center"><b>Gracias por el envío</b>.<br><br>Te agradeceríamos, no obstante y si
no resulta mucho esfuerzo, que rellenases alguno de los campos para dejar constancia de tu
visita.</div>
<?
}
?>
Si todas las comprobaciones fueron correctas, se introduce en la base de datos del libro de
visitas la información recibida como firma.
//si alguno de los campos falta prefiero colocar un guión o "sin comentarios"
if (!$nombre)$nombre="-";
if (!$email) $email="-";
if (!$comentario) $comentario="Sin comentarios";
Simplemente se hace esto para comprobar si alguno de los datos faltaba, pues en ese caso
preferimos introducir un carácter o texto especial en lugar de introducir un string vacío.
Por cierto, la variable que guarda la valoración de la página no hace falta comprobarla en
teoría, porque siempre la recibiremos bien, ya que el formulario contiene este valor en un
campo SELECT de HTML, donde siempre se selecciona un valor válido introducido por el
usuario, entre los posibles, que los define el programador de dicho campo SELECT.
Luego se debe de codificar una sentencia SQL con un INSERT con los datos del formulario. La
sentencia de inserción se realizará concatenando los datos del formulario con la propia
sentencia SQL.
Por último se muestra un mensaje dando las gracias al visitante que ha firmado el libro de
visitas.
Nota: en una carpeta del sitio necesita colocar los archivos: Index.php, estilo.css,
formul_mensaje.htm,l que se detallan a continuación.
createtable.txt
En realidad no hace falta crear un archivo con este contenido. Simplemente se debe ejecutar
este comando en algún ambiente de ejecución SQL de MySQL como por ejemplo en el cliente
mysql:
Estilo.css
A {
text-decoration : none;
color : #3333cc;
}
A:Visited {
text-decoration : none;
color : #3333cc;
}
A:Active {
text-decoration : none;
color : #3333cc;
}
A:Hover {
text-decoration : none;
color : #3333cc;
}
BODY {
font-size : 10pt;
font-family : verdana,arial,helvetica;
color : #000000;
background-color : #ddddbb;
margin-left : 0px;
margin-right : 0px;
margin-top : 0px;
margin-bottom : 0px;
}
TD {
font-size : 10pt;
font-family : verdana,arial,helvetica;
color : #000000;
}
H1 {
font-size : 13pt;
font-family : verdana,arial,helvetica;
color : #000000;
}
INPUT {
font-size: 8pt;
}
SELECT {
font-size: 8pt;
}
TEXTAREA {
font-size: 8pt;
}
.fuente8 {
font-size:8pt;
font-family: verdana,arial,helvetica;
}
Autor: Ing. Oscar R. Espeche
14
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
.fuente10 {
font-size:10pt;
font-family: verdana,arial,helvetica;
}
.titcol {
font-size : 10pt;
font-family : verdana,arial,helvetica;
background-color : #eeeecc;
color : #000000;
}
Index.php
<html>
<head>
<title>Libro de visitas</title>
<link rel="STYLESHEET" type="text/css" href="estilo.css">
</head>
<body>
<br>
<table align="center" width="550" cellspacing="2" cellpadding="8" border="0" bgcolor="#ffffff">
<tr>
<td>
<h1>Libro de visitas PHP</h1>
<?
//conecto con la base de datos
$conn = mysql_connect("servidor","usuario","password");
mysql_select_db("nombre_bbdd",$conn);
if (!$HTTP_POST_VARS)
{
//si no recibo nada por el formulario de firma del libro, muestro las firmas del libro
//construyo la sentencia SQL
$ssql = "SELECT * FROM librovisitas_php";
//se mostrarán las últimas fimas, aunque habrá un enlace en la parte de abajo que se podrá pulsar para
ver más firmas
if (isset($_GET["vermas"]))
$ssql .= " where id_librovisitas_php<=" . $vermas;
//ordeno la sentencia y limito el numero de resultados
$ssql .= " ORDER BY id_librovisitas_php desc limit 11";
Aquí puedes leer los mensajes de los visitantes y también puedes dejar el tuyo utilizando
el formulario de abajo.
<br>
<br>
<span class=fuente8><b>Muchas gracias por tu participación</b></span>
<br>
<br>
<?
//muestro los datos en un bucle
$num_filas = 0;
while (($damefila=mysql_fetch_object($resultid)) && ($num_filas<10))
{
?>
<table align="center" width="100%" cellspacing="2" cellpadding="0" border="0">
<tr>
<td valign="top" class=fuente8><b>
Autor: Ing. Oscar R. Espeche
16
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<br>
<?
$num_filas++;
} //termina el bucle while
//si quedan más valoraciones en el conjunto de resultados, muestro el enlace de "Ver más"
if ($damefila)
echo "<div align=center><b><a href=\"index.php?vermas=$damefila-
>id_librovisitas_php\">Ver más mensajes</a></b></div><br>";
Formul_mensaje.html
</table>
</td>
</tr>
</table>
</form>
Para resolver esto utilizaremos una base de datos con dos tablas, una correspondiente a los
datos de las encuestas y la otra para los datos del administrador.
Podemos tener cuatro imágenes, las cuales servirán para mostrar el resultado gráfico de la
encuesta. Cabe recalcar que el tamaño de las imágenes se puede expresar en forma
porcentual respecto de la posición donde se encuentra. Así
barra1.gif
barra2.gif
barra3.gif
barra4.gif
Antes de empezar a comenzar con el código PHP de este sistema de encuestas vamos a
describir las principales páginas involucradas.
Tendremos una primera página donde podremos ver la encuesta actual, con sus diferentes
respuestas, colocadas dentro de un formulario. Podremos elegir una respuesta y enviarla para
la contabilización del voto.
La segunda página es la que recibe los datos del formulario y los registra en la tabla de la
encuesta, añadiendo una unidad a la respuesta escogida (voto) y al campo donde
introducimos el número total de respuestas. Posteriormente, esta misma página mostrará una
tabla con los resultados parciales de la encuesta, después de la contabilización del voto
emitido por el usuario.
Página de administración
No la vamos a ver, por lo menos todavía. Serviría para editar los datos de una encuesta o
crear encuestas nuevas. Sería sólo accesible por el administrador de la página.
En nuestro caso práctico las dos páginas están unidas como una sola. En la práctica podemos
tener varias páginas que realicen encuestas y envien sus datos de los votos a una página
central que accede a la base de datos.
Aunque nuestro sistema está preparado para mostrar una única encuesta, la base de datos es
capaz de guardar varias. De este modo podríamos tener la encuesta actual y el histórico de
todas las encuestas que se han realizado en la página.
Para extraer la encuesta introducida se utilizará una sentencia SQL en la que se ordenarán las
encuestas por su identificador, de manera descendente.
Donde $encid se obtiene de alguna página inicial que define cual es la encuasta a procesar. En
nuestro caso simplemente definimos a mano el valor de la variable.
De todos modos se emplea un campo hidden (oculto) de formulario para enviar a la página de
resultados el identificador de la encuesta a la que se está votando una vez que se ha definido
la encuesta.
<?
// ***** Modificar las siguientes lineas con sus datos personalizados*****
$servidor = "localhost";
$usuario = "alumno1";
$password = "alumno";
$base_de_datos = "alumno1";
$encid = 1;
// ********************** Fin modificacion **********************
?>
<html>
<head><title>Encuestas PHP </title>
<STYLE TYPE="text/css">
P{font-family:Verdana;font-size:11px};
.boton{background-color:#ADD8EF; font-family:Verdana; color:#1605B4; font-size:10px}
</STYLE>
</head>
<body BGCOLOR="#ffffff">
<?
$miconecccion = @mysql_connect ($servidor,$usuario,$password);
if(!$miconecccion) { echo ('Imposible conectarse con MySQL,'); exit();}
if(!@mysql_select_db($base_de_datos)) { echo ('Imposible conectarse con la BD'); exit();}
<!-- los campos ocultos del numero de la encuesta y la bandera para detectar el envío-->
Autor: Ing. Oscar R. Espeche
24
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Ahora definimos nuestra pagina de resultados, la cual, lo primero que deberá hacer, es
obtener el valor de la variable voto y del identificador de la encuesta que se ha votado.
Para poder actualizar nuestra base de datos con el objetivo de registrar el voto recibido,
usaremos una instrucción de este tipo:
Como podemos observar, utilizamos el valor de la variable voto como parte del nombre del
campo a evaluar, incrementamos el mismo e incrementamos el campo total, que es donde se
acumulará el número de votos realizados. Para asegurarnos de que se incrementan sólo los
votos relacionados con la encuesta actual, con el enunciado where, limitamos la actualización
solamente a la encuesta con el identificador recibido del formulario.
obtenidos por la división del número de votos de una respuesta multiplicado por cien, entre el
número total de votos. Así para el primer valor:
También por simplicidad usamos un archivo .gif para todas las barras al que llamamos pic.gif.
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval4"]?> votos</TD>
</TR>
</TABLE>
<P ALIGN="center">Total de votos emitidos: <? echo $row["enctot"]?></P>
</td></tr>
</table>
</body>
</html>
<?
mysql_list_tables($miconecccion);
mysql_close($miconecccion);
echo "<P ALIGN=center><A HREF=".$PHP_SELF.">Volver a la encuesta</A></P>";
}?>
Sólo queda definir la página de administración de la encuesta, la cual deberá contar con un
administrador que haga posible la alteración de estos datos, esto se puede hacer con un
sistema de autentificación con clave encriptada para dar seguridad, también se puede utilizar
cookies y/o sesiones para que un usuario no vote mas de una vez en la página, y otros trucos
que pueden ser de gran utilidad para este sistema. Pero ya no son tema de estudio de este
ejemplo. Queda al ingenio del alumno y a los requerimientos del sistema.
encuesta.php
<?
// ***** Modificar las siguientes lineas con sus datos *****
$servidor = "localhost";
$usuario = "alumno1";
$password = "alumno";
$base_de_datos = "alumno1";
$encid = 1;
// ********************** Fin modificacion **********************
?>
<html>
<head><title>Encuestas PHP </title>
<STYLE TYPE="text/css">
P{font-family:Verdana;font-size:11px};
.boton{background-color:#ADD8EF; font-family:Verdana; color:#1605B4; font-size:10px}
</STYLE>
</head>
<body BGCOLOR="#ffffff">
<?
$miconecccion = @mysql_connect ($servidor,$usuario,$password);
if(!$miconecccion) { echo ('Imposible conectarse con MySQL,'); exit();}
if(!@mysql_select_db($base_de_datos)) { echo ('Imposible conectarse con la BD'); exit();}
if(!(isset($envio) && isset($voto))){
contador.txt
Archivo de texto en donde iremos acumulando el número de visitas. Su valor inicial será 0
(cero).
contador.php
contador.php
<?
Utilizando un include
Para ingresar el código dentro de la página principal de un sitio (.php por supuesto)
utilizaremos un include. Entonces, en la página index.php ingresamos la siguiente línea en
donde queremos que aparezca el contador:
<?
include("contador.php");
?>
Nota: Se usa una @ antes del nombre de las funciones como se observa en el código, para
evitar la salida hacia el navegador de los mensajes de advertencia que avisan que el archivo
.txt no existe la primera vez que se ejecuta el código.
Para modificar este tiempo de vida máxima de una sesión puede hacerse en el php.ini a partir
del parámetro session.gc_maxlifetime donde expresaremos dicho plazo en segundos.
Ojo, este tiempo máximo es restaurado a su valor inicial cada vez que el usuario realiza una
petición al servidor, esto quiere decir que un visitante podrá navegar cuanto tiempo quiera por
el sitio guardando la misma sesión siempre y cuando no se quede más de 24 minutos sin
realizar ningún tipo de acción.
Para el correcto funcionamiento del script, es necesario antes de nada crear una tabla en
nuestra base de datos. Esta sentencia SQL puede ayudaros en la tarea:
CREATE TABLE control_ip (ip VARCHAR (15) NOT NULL, fecha INT (14) UNSIGNED NOT
NULL, INDEX (ip));
Como ven, el campo ip, que almacena el número IP del visitante, está indexado. Esto nos
permitirá una selección rápida. Lo importante en efecto es que el script se ejecute
rápidamente sin consumir demasiados recursos del servidor, sobre todo teniendo en cuenta
que se trata de un código que será sistemáticamente ejecutado en cada una de las páginas
del sitio.
Contar.php
<?
function usuarios_activos()
{
//permitimos el uso de la variable portadora del numero ip en nuestra función
global $REMOTE_ADDR;
Autor: Ing. Oscar R. Espeche
32
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
//actualizamos la tabla
//borrando los registros de las ip inactivas (24 minutos)
$limite = $ahora-24*60;
$ssql = 'delete from control_ip where fecha < '.$limite;
mysql_query($ssql,$conn);
//liberamos memoria
mysql_free_result($result);
Autor: Ing. Oscar R. Espeche
33
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
//devolvemos el resultado
return $usuarios;
}
?>
Para sacar el valor proporcionado por la función a nuestro script principal tendremos que
realizar una llamada clásica del tipo:
$uactivos = usuarios_activos();
He aquí en definitiva un script sencillo que puede dar a nuestro sitio una imagen un poco más
dinámica. Además, podemos utilizarlo y mejorarlo para crear nuestro propio sistema de
estadísticas internas.
activos.php
<?
include ('contar.php');
$usuarios = usuarios_activos();
?>
<html>
<head></head>
<body>
<center>
<table bgcolor = #dedede>
<tr>
Autor: Ing. Oscar R. Espeche
34
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<td>
<b>Usuarios Conectados Actualmente: <?= $usuarios?><b>
</td>
</tr>
</table>
</center>
</body>
</html>
Para el envío de correos electrónicos utilizando PHP disponemos de una función bastante
potente, incluida en todas las versiones de PHP, sin necesidad de instalar ningún añadido, en
contra de lo que ocurría con ASP.
En concreto, en PHP disponemos de una función llamada mail() que permite configurar y
enviar el mensaje de correo. La función recibe tres parámetros de manera obligada y otros dos
parámetros que podemos colocar opcionalmente.
Asunto: para indicar una cadena de caracteres que queremos que sea el asunto del correo
electrónico a enviar.
Cuerpo: el cuerpo del mensaje, lo que queremos que tenga escrito el correo.
<?
mail("pepito@pepe.com,maria@yahoo.com","un asunto","Este es el cuerpo del mensaje")
?>
Headers: Cabeceras del correo. Datos como la dirección de respuesta, las posibles
direcciones que recibirán copia del mensaje, las direcciones que recibirán copia oculta, si el
correo está en formato HTML, etc.
<?
Autor: Ing. Oscar R. Espeche
36
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
$destinatario = "pepito@pepe.com";
$asunto = "Este mensaje es de prueba";
$cuerpo = '
<html>
<head>
<title>Prueba de correo</title>
</head>
<body>
<h1>Hola amigos!</h1>
<p>
<b>Bienvenidos a mi correo electrónico de prueba</b>. Estoy encantado de tener tantos usuarios.
</p>
</body>
</html>
';
mail($destinatario,$asunto,$cuerpo,$headers)
?>
Nota: Antes de poner en marcha el script en el servidor, por favor, cambiar los datos de
configuración de las direcciones de correo que van a recibir el mensaje y colocar unas
direcciones que sean reales y donde se pueda comprobar si los mensajes se envían
correctamente.
Nota: Para el envío de correo mediante PHP es necesario que este disponga de una correcta
configuración.
PHP se configura en el archivo php.ini, donde debemos especificar datos como el servidor de
correo saliente que debe de utilizar PHP para transferir los mensajes.
Dentro del php.ini, debemos buscar el epígrafe [mail function]. Dependiendo de nuestro
sistema deberemos configurar de una manera u otra.
Uso de formularios
Para completar este ejercicio construiremos un formulario que permita cargar por http los
datos del mail.
formulario.htm
<html>
<head><title>Envio de emails con PHP</title></head>
<body>
<form action="enviar.php" method="post" target = "_blank">
<center>
<table bgcolor = #bcbcbc border = 1>
<tr>
<td align = "right" ><b>Para:</b></td>
<td><input type="text" name="destino" size="30"></td>
</tr>
<tr>
<td align = "right" ><b>De:</b></td>
<td><input type="text" name="remitente" size="30"></td>
</tr>
<tr>
<td align = "right"><b>Bcc:</b></td>
<td><input type="text" name="bcc" size="30"></td>
</tr>
<tr>
<td align = "right"><b>Ccc:</b></td>
<td><input type="text" name="ccc" size="30"></td>
</tr>
<tr>
<td align = "right"><b>Reply:</b></td>
<td><input type="text" name="responder" size="30"></td>
</tr>
<tr>
<td align = "right"> <b>Asunto:</b></td>
Autor: Ing. Oscar R. Espeche
38
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<tr>
<td><input type="submit" value="Enviar!"></td>
<td></td>
</tr>
</table>
</center>
</form>
</body>
</html>
enviar.php
<?
if($destino!=""){
Vamos a ver una función muy útil en PHP que sirve para comprobar la validez de un correo.
En realidad comprueba si una dirección de correo electrónico está bien escrita sintácticamente,
dejando de lado las comprobaciones de si ese mail existe o no realmente, que no se pueden
hacer tan fácilmente.
Vamos a escribir una función que se llama comprobar_email y recibe la cadena de texto con el
email que queremos validar. Si dicho email es correcto desde el punto de vista sintáctico, es
decir, si tiene un nombre de usuario, una arroba y una terminación con el nombre de un
dominio o subdominio, etc, devolverá un 1, es decir, verdadero. En caso de que el email no
esté correctamente escrito, la función devolvería 0, que equivale a falso.
La función en si da por hecho inicialmente que el email es erróneo y realiza una serie de
comprobaciones que, si todas responden correctamente, dan por conclusión que el email sí
estaba bien escrito. Si alguna de esas comprobaciones no era correcta, no se llegaría al final
de las comprobaciones y quedaría el resultado como se ha supuesto en un principio, es decir,
como incorrecto.
<?function comprobar_email($email){
$mail_correcto = 0;
//compruebo unas cosas primeras
if ((strlen($email) >= 6) && (substr_count($email,"@") == 1) && (substr($email,0,1) != "@")
&& (substr($email,strlen($email)-1,1) != "@")){
if ((!strstr($email,"'")) && (!strstr($email,"\"")) && (!strstr($email,"\\")) &&
(!strstr($email,"\$")) && (!strstr($email," "))) {
//miro si tiene caracter .
if (substr_count($email,".")>= 1){
//obtengo la terminacion del dominio
$term_dom = substr(strrchr ($email, '.'),1);
//compruebo que la terminación del dominio sea correcta
if (strlen($term_dom)>1 && strlen($term_dom)<5 && (!strstr($term_dom,"@")) ){
//compruebo que lo de antes del dominio sea correcto
$antes_dom = substr($email,0,strlen($email) - strlen($term_dom) - 1);
$caracter_ult = substr($antes_dom,strlen($antes_dom)-1,1);
if ($caracter_ult != "@" && $caracter_ult != "."){
$mail_correcto = 1;
}
}
}
}
}
if ($mail_correcto)
return 1;
Autor: Ing. Oscar R. Espeche
40
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
else
return 0;
}
?>
Las comprobaciones
En el primer if compruebo que el email tiene por lo menos 6 caracteres (el mínimo), que tiene
una arroba y sólo una y que no está colocada ni al principio ni al final.
Finalmente, se devuelve la variable local utilizada para guardar la validez o incorrección del
correo.
Para hacer uso de esta función simplemente deberemos incluir el archivo que contiene a dicha
función y ejecutarla simplemente. De acuerdo a esto el código quedaría de la siguiente
manera:
enviar.php
<?
Include ('comprobar.php');
$mail1 = comprobar_email($destino);
$mail2 = comprobar_email($remitente);
if ($responder){
$mail3 = comprobar_email($responder);}
else {
$mail3 = 1;
}
if ($ccc){
$mail4 = comprobar_email($ccc);}
else {
$mail4 = 1;
}
if ($bcc){
$mail5 = comprobar_email($bcc);}
else {
$mail5 = 1;
}
Autor: Ing. Oscar R. Espeche
41
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
if($mail1&&$mail2&&$mail3&&$mail4&&$mail5){
//dirección del remitente
$headers="From: '".$remitente."'"."\r\n";
//dirección de respuesta, si queremos que sea distinta que la del remitente
$headers.="Reply-To: '".$responder."'"."\r\n";
//direcciones que recibirán copia
$headers.="Cc: '".$ccc."'"."\r\n";
//direcciones que recibirán copia oculta
$headers.="Bcc: '".$bcc."'"."\r\n";
echo "<p><b> Se está enviando el mensaje.......</b><p>";
mail($destino, $asunto, $mensaje, headers);
echo "Se ha enviado el mensaje a $destino correctamente!";
}
else{
echo "Debes escribir direcciones de correo válidas para poder enviar el e-Mail";
}
?>
Existen muchas formas de comunicarnos con el navegante, vamos a ver los mecanismos que
están más a nuestro alcance para que a ninguna de nuestras webs les falte la posibilidad de
comunicarse con sus visitantes.
Hemos ordenado los siguientes puntos por orden de facilidad en su uso, así los primeros son
más asequibles y los siguientes más difíciles de conseguir, aunque a menudo mejores.
Lo que nunca debe faltar en una página, por su sencillez y utilidad, por que es la forma más
adecuada en muchos casos... Siempre tenemos que incluir una dirección de correo, fácilmente
localizable, para que los visitantes puedan comunicarse. Es facilísimo hacer un enlace con una
dirección de correo:
<A HREF="mailto:pepe@pepe.com">Escríbeme</A>
El problema de esta solución es que se requiere que en la computadora del usuario esté
correctamente configurado su cliente de correo electrónico.
Formulario de contacto
Esto es lo que explicamos en el tema de envío de mails por PHP. En este caso donde la
dirección de destino ya está pre-definida, se la envía en un campo “hidden” del formulario y
Autor: Ing. Oscar R. Espeche
43
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
no se muestra al usuario. Normalmente solo se deja para que sea rellenado por el usuario su
dirección de correo, el asunto (puede ser opcional) y el texto (que también puede ser opcional
en algunos casos).
Las ventajas de un formulario con respecto a una dirección de correo pueden ser:
Listas de correo
Una lista de correo es una dirección de e-mail a la que si enviamos un correo nos lo hace
llegar a todos los integrantes de una lista de direcciones.
Con un ejemplo estará más claro. Si todos los integrantes de una lista, cuando quieren
conversar entre ellos, en vez de mandar un correo electrónico a cada uno de ellos, lo mandan
a la lista de un servidor de listas y este se encarga de que le llegue el mensaje a todos los
miembros de la lista.
Las listas de correo pueden ser muy útiles para que los usuarios que lleguen a las páginas se
anoten como miembros de la misma, y nosotros, como administradores del sitio web
mandaremos correos electrónicos periódicamente a las lista para mantenerlos informados de
noticias, cambios en el web y todo aquello que queramos enviarles.
Estas listas de correo pueden tener usos diversos, pero en un sitio Web el uso principal es
para enviar boletines de novedades.
Boletines de novedades
Cualquier web que se precie debe mantener también un buen boletín de novedades. No quiere
decir que debamos acometer este trabajo para llegar a un estatus elevado, sino más bien, que
las ventajas de dicho boletín son las que harán que nuestra página suba de categoría. Los
boletines nos dan más presencia y recuerdan a los visitantes la existencia de la web cada mes,
con lo que animan a visitarla. Veamos con detalle estas ventajas.
Precisamente este alto grado de respuesta y el interés que suscita un buen boletín hacen de
este canal un lugar muy apropiado para colocar mensajes publicitarios, en forma de texto, o
banners si nuestro boletín se distribuye en formato HTML. Así mismo, si nuestro sitio es de
comercio electrónico, el boletín es el lugar apropiado para introducir las ofertas más
importantes del momento. Por las mismas razones, los boletines suelen se un excelente lugar
para realizar intercambios de publicidad, si es que no tenemos otro tipo de ofertas para
rellenar nuestros espacios publicitarios.
Los boletines sirven para promocionar los nuevos servicios que ofrecemos en nuestro
web, cuando aun son poco conocidos y pretendemos que los usuarios lleguen hasta ellos.
Habrá usuarios que prefieran apuntarse al boletín antes de visitarnos constantemente para ver
si hay novedades, por lo que debemos ofrecer la posibilidad de que nuestras novedades
lleguen perfectamente a su correo.
Poco a poco, los visitantes se irán apuntando a nuestro boletín de novedades. Dependiendo
del tema de nuestra web se apuntarán más o menos personas, ya que puede resultar más
interesante a un visitante y puede abarcar más audiencia recibir un chiste a la semana que la
información bursátil.
En cualquier caso y con el tiempo, podremos obtener una lista de usuarios suscritos a nuestro
boletín de una cantidad considerable: varios cientos o miles. Podríamos escribir un mensaje de
correo electrónico dirigido "manualmente" a todos esos usuarios y enviarlo con nuestro
programa de correo, pero eso no va a ser siempre lo más adecuado.
puede que nos resulte muy rápido y sencillo. En este caso es importante indicar
todos los destinatarios en el campo BCC o CCO (Copia Carbón Oculta) de nuestro
mensaje de correo, que es el campo donde indicamos las personas que van a recibir
una copia oculta del correo. Si indicásemos todas las direcciones en el campo TO o
PARA o en el campo CC (Copia Carbón o Carbon Copy), nuestros destinatarios
conocerían las direcciones de correo de los otros suscritos al boletín y alguno podría
utilizarlas para mandarles mensajes spam (publicidad no deseada) al resto de
componentes del grupo.
Como vemos, es mejor que contemos con un servicio de envío masivo de mails. Estos servicios
suelen ser listas de correo, que consisten en una lista de direcciones de correo de
destinatarios y un mecanismo para que cuando se envíe un mensaje a la lista, se explote para
todos sus componentes. Estas listas de correo, además de realizar por nosotros la acción de
envío de los mensajes, se encargarán de preservar la identidad de los componentes del
boletín.
Otra tareas de mantenimiento de la lista de correo del boletín que tenemos ya implementadas
en este servicio suelen ser dar de alta o baja direcciones de correo, con lo que no tenemos
que realizar difíciles scripts para suscribir o borrar direcciones. También hay listas que
comprueban los mensajes para que no contengan virus, que nos ofrecen un histórico de los
boletines emitidos, etc. Todo depende de la lista de la que dispongamos.
Otras opciones
También podríamos hacer un programa propio que mande correos masivamente utilizando
ASP o PHP, pero en caso de enviar miles de mensajes, habría evaluar la posibilidad de
saturación del servidor donde tenemos alojadas las páginas, que puede no estar preparado
para una tarea como esa.
El uso de estas herramientas para el envío de nuestros boletines tiene algunas ventajas e
inconvenientes. Como ventaja podemos señalar que los sistemas de listas de correo gratuitas
están preparados para enviar mensajes de correo de manera masiva y que, aunque enviemos
cientos de miles de emails, no habrá problema de saturación de sus servidores. Como
desventaja, la lógica inserción de publicidad por parte del proveedor en nuestros boletines,
necesaria para mantener su servicio.
Otra opción para mandar los correos sin necesidad de una lista gratuita sería tener nuestra
propia lista de correo. Muchos alojamientos tienen como recursos la posibilidad de crear listas
de correo, sólo habría que preguntar en nuestro proveedor de hosting acerca de esa
posibilidad, o cuando contratemos los servicios asegurarnos que nos ofrecen esa posibilidad.
Nota: En ocasiones las listas de correo de los proveedores de Hosting no son tan
Autor: Ing. Oscar R. Espeche
46
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
buenas como las gratuitas, puesto que las listas gratuitas se han desarrollado con la
experiencia probada de miles de administradores.
Para conocer mejor el tema de listas de correos gratuitas nos remitiremos a los proveedores
de listas como por ejemplo, en el caso de Elistas.net que tiene un excelente manual de
utilización
Un detalle que salta a la vista pero que creo interesante comentar, es que la lista de correo
que mantiene el boletín debe estar configurada para que sólo acepte mensajes venidos desde
la dirección del administrador de la lista, porque en caso contrario, cualquiera podría enviar
mensajes de correo a todos los suscritos al boletín haciendo spam a tus usuarios, que siempre
es bastante molesto.
Resumen:
Como siempre. Procura decir lo interesante en el primer párrafo. Deja lo demás para el final.
Quien manda el mail. Si utilizas un alias para enviar el mail procura que se te pueda identificar
y responder a ese mismo alias.
En el subject procura decir el tema del mail de forma clara y sencilla. Algo así como
"Actualización del sitio", "Rebajas de Enero", "Opina sobre el precio de la carne".
El primer párrafo debe decirlo todo de forma clara y sencilla. Incluyendo los links a las paginas
que se haga referencia.
Yo no soy muy partidario del sumario en las newsletters. Lo único que hace es ocupar espacio
y restar tiempo a leer el tema principal. Mejor poner el tema principal y si deseas incluir mas
temas, ponlos debajo indicando claramente que estos son temas secundarios que pueden ser
de interés para el usuario.
Autor: Ing. Oscar R. Espeche
47
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Por ultimo incluye el típico "borrar suscripción", "incluir suscripción" y un enlace a tu sitio.
En el caso del mail más aún. La lectura del mail no es algo relajante, mas bien la gente suele
estar algo "tensa" (Nielsen), por lo que cuando antes lean el tema antes se relajaran y
seguirán leyendo. Si empezamos el mail diciendo cosas como, "Acabas de recibir una oferta
que no podrás rechazar..." lo único que conseguiremos es que lo tiren a la basura. Mejor
empezar con cosas del estilo "Rebajas del 40% en la sección de discos. Pinche en este
enlace." y luego podemos seguir describiendo de qué va esta promoción para que el usuario
se informe bien del tema antes de pinchar. Pero procura reducir al máximo lo que tengas que
decir.
Para enviar páginas web completas por el mail. Suelen pesar mucho y ocupan mucho espacio.
Ten en cuenta que la ventana de mail suele ser mas pequeña que el navegador.
Para incluir imágenes en el mail. Es mejor que indiques que dispones de imágenes en tu sitio y
el enlace a dicha foto.
Mucha gente lee el correo en casa donde la conexión puede ser peor que en el trabajo con lo
que le costara mucho bajarse documentos complejos. Procura no abusar del correo y procura
no enviar imágenes gratuitamente.
4. Como mínimo una vez al mes. Como máximo una vez a la semana.
Conviene enviar un mail de bienvenida cada vez que alguien se registre en tu servicio. Esto
confirmara que el sistema funciona y que estamos en la lista.
Como mínimo una vez al mes. Es recomendable enviar una newsletter al mes. Por lo
menos para que la gente sepa que sigues vivo y que la cosa sigue en marcha. Si pasa mucho
tiempo entre una newsletter y otra la gente se puede olvidar de ti y no reconocerte la próxima
vez que les escribas.
Como máximo una vez a la semana. Tampoco conviene abusar de los usuarios y más de
una vez a la semana puede considerarse "Spam". De todos modos procura enviar por mail solo
aquellos eventos relevantes que ocurran en tu sitio. Si no ocurre nada no tienes por que enviar
nada. Un mail que no tenga valor ira directamente a la basura y puede hacer que el usuario
bloque la dirección de correo de origen.
Muchas veces cuando ocurre algo importante (un virus,...) la gente suele tomar su lista de
correo completa y envía un mail a "todo el mundo"... Esto a veces genera que alguien de la
lista copie todas las direcciones y se dedique a hacer spam...
Para evitar esto, sencillamente copia tu lista de correo en el BCC y así no será publica para el
resto del mundo.
Nuestro mensaje de correo electrónico para enviar al boletín ha de tener formato HTML, dado
que dicho formato es imprescindible para insertar imágenes en el correo y para la inserción de
enlaces y otros elementos.
Podríamos proponer dos técnicas para la inserción de imágenes en el boletín. Aunque sólo
vamos a ilustrar una de ellas, merece la pena comentar las dos para que quede todo mucho
más claro.
Esta opción es interesante porque así nos aseguramos que las imágenes que salen en el
mensaje se verán siempre perfectamente. Es la opción más complicada y no veremos su
implementación. Además, tiene la desventaja de que el mensaje pesa más y lo peor es que
contiene archivos adjuntos. El problema de tales archivos adjuntos es que pueden contener
virus, mientras que un mensaje sin archivos adjuntos es casi imposible que contenga virus.
Lo que se hace es que cualquier imagen que aparece en el boletín se extrae directamente
desde su dirección de Internet, de modo que cuando se lee el correo se accede a la dirección
en la web que contiene dicha imagen y no a un archivo adjunto al mensaje. Esta opción es
mucho más fácil de desarrollar y también más segura, puesto que el mensaje llegaría sin datos
adjuntos y por tanto con menores posibilidades de virus. El único problema es que si el
usuario no está conectado a Internet a la hora de leer el mensaje las imágenes aparecerán
"rotas" y no saldrán en el cuerpo del correo hasta que el usuario se conecte.
Así pues, que es lo más conveniente: no enviamos correos con archivos adjuntos. Lo que
hacemos es enviar el mensaje en formato HTML y enlazar todas las imágenes, otros recursos y
links con URLs absolutas.
Lo que hacemos es crear la página con un editor, tal como deseamos que se envíe,
pero poniendo todas las direcciones de los enlaces y las imágenes dirigidas
hacia páginas e imágenes que están en la web (http://....) , en lugar de dirigirlas a otras
páginas e imágenes que están en tu disco duro.
Así, los atributos HREF de los enlaces y los SRC de las imágenes quedarían con URLs
absolutas:
Vistos los códigos de unos ejemplos de imágenes y enlaces podemos imaginarnos el código de
la página entera. Un código HTML perfectamente común donde, insisto, tenemos URLs
absolutas en todos los recursos con los que hay que enlazar.
Ten en cuenta que no bajas la página de un sitio web sino que la habres en tu computadora.
Hay una etiqueta que también solemos incluir dentro del código HTML del boletín, en este
caso para conseguir que todos los enlaces se muestren en una ventana a parte y no dentro
del cuerpo del mensaje. De este modo, la navegación sobre los contenidos de nuestra web se
realizará con todo el espacio de la ventana del navegador.
<base target="_blank">
Una vez creada la página web -una página HTML normal, con todos los enlaces e imágenes
con URLs absolutas- la debemos incluir en un mensaje de email.
<html>
<head><link rel="STYLESHEET" type="text/css" href="http://www.pepe.com/estilo.css">
<base target="_blank">
</head>
El programa de correo que utilices tendrá su propia manera de incluir código HTML dentro de
un mensaje. En Outlook Express hay que acceder al menú de Insertar > Texto de archivo. Si
Autor: Ing. Oscar R. Espeche
51
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
el mensaje que estás escribiendo tiene formato HTML, podrás insertar archivos que tengan
extensión .html o .htm. Indico esto porque en el caso de que tu email estuviera en formato
"solo texto", sólo podrías insertar archivos de texto .txt. Para cambiar el formato de mensaje a
HTML en Outlook Express debemos dirigirnos al menú Formato > Texto enriquecido (HTML).
Atención: Al insertar el código del archivo HTML dentro del boletín hay que fijarse
en no insertar el archivo HTML como un archivo adjunto, sino en insertar el código
de dicho archivo como texto en el mail. En Outlook Express es fácil equivocarse pues
las dos opciones están una al lado de la otra, en el menú insertar. En este programa
hay que escoger la opción "Insertar > Texto de archivo" en lugar de "Insertar >
Archivo adjunto".
Una vez compuesto el mensaje lo enviamos a nuestra lista de correo, que se encarga de
distribuir los mensajes a los miles de suscriptores del boletín. Generalmente, las listas de
correo tienen una dirección a la que mandar los mensajes de correo que queremos dirigir a
todos los componentes de la lista, algo como
miLista_recepción@miProveedor.net.
En general, el envío del mensaje en formato HTML será realizado de la misma manera que un
mensaje en formato normal, excepción hecha de lo comentado. Esperamos que no resulte un
problema.
Hasta aquí nuestros consejos sobre el envío de boletines en formato HTML, así como la
creación de boletines de novedades en general. Ahora, a poner en práctica las ideas.
Resumen.
2. El "Tema" (subject) del mail debe ser corto y honesto. Debe suscitar cierta curiosidad.
2. En el "Quien" procura ofrecer información honesta y utilizar una dirección de correo a la
que se pueda responder.
2. Ofrece información clara y útil. Debes generar Acción.
2. Enlaza a páginas que ofrezcan la misma información que en el e-mail mas las opciones
adicionales (evita el enlazar a la portada o a páginas de registro).
2. Prueba el mail en grupos reducidos para corregir.
2. Lanza diferentes versiones para testear resultados.
1. El "tema" del mail debe ser corto y honesto. Procura suscitar cierta curiosidad.
El "quien" y el "tema" sirven para que el usuario abra o borre directamente el mail recibido.
Autor: Ing. Oscar R. Espeche
52
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
En el quien ofrece signos de identificación reales. Un nombre de persona puede generar mas
confianza que un "departamento" o un mail del estilo "info@empresaXXX.com". Procura que
en "alias" del quien aparezcan signos que identifiquen la empresa. Usar el dominio puede ser
suficiente (Juan Sanchez - empresa.com).
Procura que la dirección de correo de la newsletter sea una dirección a la que se pueda
responder. De lo contrario, tendrás que poner instrucciones para explicar la situación, lo cual
puede entorpecer la posibilidad de captar un cliente.
El mail al que se responde debe estar respaldado por gente que sea capaz de responder de
forma rápida y precisa.
Tienes 5 segundos para captar la atención del usuario. Cualquier segundo de duda hará que el
usuario pulse el botón de borrar.
Usa HTML para formatear el contenido y crear "destacados" dentro del texto. Es importante
ofrecer titulares con gancho e información que le sirva de apoyo.
La información fundamental no debe estar dentro de los gráficos. Los gráficos pueden
servir para ilustrar el contenido y para ofrecer imagen de calidad y confianza.
Procura ofrecer un "que", "cuando", "cuanto" y "como" que generen acción (visitar una web,
llamar, responder al correo).
4. Enlaza a páginas que ofrezcan la misma información que en el e-mail más las
opciones adicionales.
Procura probar diferentes versiones y compara cual da mejor resultado. Comprueba que tipo
de enlaces, imágenes, texto, formato es el mas efectivo y comprueba técnicamente que todo
vaya a funcionar de forma efectiva (los enlaces, el formato, el peso).
Una de las ventajas de las newsletters e internet es que se pueden medir con bastante
facilidad la respuesta de los usuarios.
Puedes enviar el mismo contenido variando el formato para comprobar cual es mas efectivo,
que tipo de masaje es mas apropiado, etc. La economía del medio y la facilidad de procesar
los datos hace que sea un buen campo de experimentación.
Procura no abusar de la paciencia de los usuarios (para newsletters corporativas 1 envió cada
2 meses puede ser adecuado) y gratifica de alguna forma la respuesta del usuario.
Libro de visitas
Ahora veremos algún mecanismo adicional para comunicarse con el cliente, pero en estos
casos no se trata tanto de una comunicación entre ellos y tu, sino más es una forma de
comunicación te todos para todos.
En el caso del libro de visitas está bien claro, es una herramienta donde los visitantes pueden
dejar los mensajes que deseen para que estos queden reflejados en la web y así, no sólo los
leas tu, sino que también los pueden leer todos los demás usuarios de tus páginas. Esto le da
agilidad a la página, dinamismo y hace que los visitantes se sientan integrados en el proyecto,
colaboren y vuelvan para ver sus "huellas". Las ventajas son muchas.
En nuestro caso podrás experimentar con el libro de visitas del ejemplo ya presentado.
Foros de discusión
En algún caso podemos pasar a una opción más avanzada de lo que nos ofrecía libro de
visitas. Estos son los Foros de discusión, donde la gente puede opinar sobre temas y otros
navegantes contestarles, etc. Es muy útil e interesante. No cabe ya destacar sus múltiples
ventajas y hits que recibiremos si se tratan temas de interés.
Si no tenemos la infraestructura suficiente para montar nosotros el foro, podemos utilizar los
servicios, muchas veces gratuitos, de otros servidores.
Conclusión
Hemos visto un montón de ideas para incluir en nuestras páginas, todas ellas con el objetivo
de establecer contacto con el visitante, aunque al final se nos ha ido el tema del
planteamiento inicial y hemos incluido mucho más que meras herramientas de marketing.
Porque no olvides que todo esto es para hacerte conocer y hacer que los visitantes te
recuerden con alegría y a menudo.
Esta conexión está regida por el mecanismo común que relaciona cliente con servidor. Por lo
tanto mediante “sockets” es posible comunicar programas en una misma computadora o en
computadoras diferentes a través del protocolo TCP/IP.
Se puede trabajar con diferentes lenguajes de programación quienes con sus respectivas API
conectarán con los “sockets” para abrir una conexión en una red TCP/IP.
PHP posee sus propias API y funciones que nos permiten trabajar con estas conexiones
conocidas como “sockets”.
Una de las particularidades de estos “sockets” es que hay que abrirlos, cerrarlos, grabar y leer
con una semántica similar al manejo de archivos. Es más, existen funciones que son comunes
para archivos y “sockets”.
El cliente debe abrir también un “sockets” pero con la dirección Ip por defecto del cliente y en
un puerto libre elegido por el sistema.
Una vez abiertos los “sockets” en cliente y servidor se lleva acabo la conexión mediante el
intercambio de cadenas de caracteres que deben ser interpretadas por los programas que
intervienen en el diálogo.
Normalmente los servidores que trabajan con un protocolo ya definido por alguna RFC tienen
bien en claro cuales son las cadenas que deben intercambiar con el cliente.
Por su parte el cliente que sabe con que servicio se conecta y a que RFC atenerse, también
sabe cuales son las cadenas válidas para hacerle consultas al servidor y cuales son las
respuestas posibles de éste.
En realidad la mayoría de los programas se comunican por medio de los “sockets”. Por
ejemplo un servidor de Web se conecta como tal al puerto 80 mediante un “sockets” y el
cliente se dirige a éste para solicitarle servicio.
Autor: Ing. Oscar R. Espeche
56
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
PHP debe ser configurado con la directiva "--enable-sockets" para disponer de las varias
funciones que dispone para este fin. En Windows donde se dispone normalmente de un
binario ya compilado dispone de esta posibilidad por defecto en algunas de las distribuciones.
De todas forma siempre podemos descubrir esta configuración mediante la función phpinfo()
como ya sabemos.
Veamos el siguiente ejemplo simple de servidor, que recibe las cadenas, las invierte y las
devuelve al cliente.
server.php
<?
// definición de la dirección Ip y puerto del servidor
$host = "172.16.10.178";
$port = 1234;
// sin timeout
set_time_limit(0);
// crea el socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Error al crear el socket\n");
// invierte la cadena
$output = strrev($input) . "\n";
?>
<?
$host = "172.16.10.178";
$port = 1234;
?>
<?
set_time_limit(0);
?>
<?
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("..........");
?>
<?
$socket = socket_create(AF_INET, SOCK_DGRAM, 0) or die("............");
?>
<?
$result = socket_bind($socket, $host, $port) or die("...............");
?>
<?
$result = socket_listen($socket, 3) or die("...............");
?>
En este punto el servidor espera al cliente sin hacer nada. Una vez que se recibe la petición
del cliente, la función socket_accept() entra en acción aceptando la solicitud y generando
otro socket hijo para permitir mediante éste la conexión futura con el cliente. Mientras
tanto sigue esperando en el primer socket asociado al puerto bien conocido la solicitud de
otro cliente. Con cada cliente reacciona de la misma manera, creando un nuevo sockets
hijo para dicho cliente.
<?
$spawn = socket_accept($socket) or die("..............");
?>
<?
$input = socket_read($spawn, 1024) or die("..................");
?>
El segundo parámetro indica la cantidad de bytes a leer como máximo del buffer.
Note que la función socket_read() continúa leyendo los bytes hasta que encuentra un
carácter especial nueva línea (\n), un tab (\t) o un \0. Cualquiera de estos caracteres es
tratado como fin de línea, terminando con la función.
<?
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen ($output)) or die("........");
?>
<?
socket_close($spawn);
socket_close($socket);
?>
El problema que se nos presenta ahora es disponer de una instalación de PHP ejecutable que
se puede instalar desde un PHP fuente sin la opción de configuración "--with-apache" y luego
compilando.
php -q server.php
Como cliente usamos al programa Telnet que emite cadenas mediante la apertura de sockets
en nuestra computadora cliente, de acuerdo a lo que mostramos seguidamente:
Hola como te va
av et omoc aloH
El siguiente sería una versión mejorada del anterior que funciona con php.exe para Windows.
Debemos ubicarnos en el directorio c:\appserv\php para ejecutar php.exe.
<?
// definición de la dirección Ip y puerto del servidor
$host = "172.16.10.178";
$port = 1234;
Autor: Ing. Oscar R. Espeche
60
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
// sin timeout
set_time_limit(1000);
// crea el socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Error al crear el socket\n");
// invierte la cadena
$output = strrev($input) . "\n\r";
//$output = "hola como te va cliente";
// devuelve la cadena invertida
$saludo="Enviando salida:\n\r\n\r";
socket_write($spawn,$saludo , strlen ($saludo)) or die("Error de escritura\n");
socket_write($spawn, $output, strlen ($output)) or die("Error de escritura\n");
$i="";
}
// cierra los sockets
socket_close($spawn);
socket_close($socket);
?>
El programa cliente
Hasta ahora nos conectamos con el cliente Telnet. Sin embargo es muy fácil escribir nuestro
propio cliente PHP.
Cliente.php
<html>
<head>
</head>
<body>
<?
if (!$submit)
{
?>
<?
}
else
{
$host="172.16.10.178";
$port = 1234;
// apertura de la conexión del cliente
$fp = fsockopen ($host, $port, $errno, $errstr);
if (!$fp)
{
$result = "Error, no se pudo abrir la conexión";
}
else
{
// tomar el mensaje de bienvenida
fgets ($fp, 1024);
// tomar la contestación
$result = fgets ($fp, 1024);
// cerrar la conexión
fputs ($fp, "END");
fclose ($fp);
// limpiar la respuesta
$result = trim($result);
Cliente2.php
<html>
<head>
</head>
<body>
<?
if (!$submit)
{
?>
<?
}
else
{
$host="172.16.10.178";
$port = 1234;
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("............");
$result = socket_connect($socket, $host, $port) or die("............");
socket_read ($socket, 1024) or die("....................");
socket_write($socket, $mensaje, strlen($mensaje)) or die("................");
$result = socket_read ($socket, 1024) or die("................");
socket_write($socket, "END", 3) or die("....................");
socket_close($socket);
$result = trim($result);
$result = substr($result, 0, strlen($result)-1);
Autor: Ing. Oscar R. Espeche
63
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
?>
Mensaje del servidor: <b><? echo $result; ?></b>
<?
}
?>
</body>
</html>
En este caso se usó la función socket_connect() para abrir la conexión con el servidor, y las
funciones socket_read() y socket_write() para la recepción y envío de datos.
Lo que hace falta saber es el flujo de cadenas entre el cliente y el servidor. Para eso nos
conectamos con nuestro servidor POP3 mediante Telnet y probamos. En negrita se indican
nuestros comandos. El resto es la respuesta obtenida del servidor POP3.
USER juan
+OK User name accepted, password please
PASS clave
+OK Mailbox open, 72 mensajes
STAT
+OK 72 24595628
QUIT
+OK Sayonara
Connection closed by foreign host.
<?
$host="192.168.0.202";
$port = 110;
$user = "juan";
$pass = "clave";
if (!$fp)
{
die("Error: no se pudo abrir el socket");
}
else
{
//tomar el mensaje de bienvenida
$welcome = fgets ($fp, 150);
// chequear si estuvo OK
if (substr($welcome, 0, 3) == "+OK")
{
// enviar el nombre del usuario y tomar la respuesta
fputs ($fp, "USER $user\n");
fgets($fp, 50);
// chequear si estuvo OK
if (substr($ack, 0, 3) == "+OK")
{
// enviar status y tomar respuesta
fputs ($fp, "STAT\n");
$status = fgets($fp, 50);
if (substr($status, 0, 3) == "+OK")
{
// cerrar conexión
fputs ($fp, "QUIT\n");
fclose ($fp);
}
// error con STATUS
else
{
die ("Status: $status");
}
}
// si falló la autenticación
else
{
die ("Server dice: $ack");
}
}
// si no se pudo conectar con el servidor
else
{
die ("No se pudo conectar con el servidor\n");
}
Autor: Ing. Oscar R. Espeche
65
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<?
set_time_limit(0);
$host = "192.168.1.202";
$port = 1234;
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n");
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n");
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n");
$input = socket_read($spawn, 1024) or die("Could not read input\n");
$input = trim($input);
$arr = explode(":", $input);
$result = authenticate(trim($arr[0]), trim($arr[1]));
socket_write($spawn, $result, strlen ($result)) or die("Could not write output\n");
socket_close($spawn);
socket_close($socket);
if ($arr[0] == $user)
{
Autor: Ing. Oscar R. Espeche
66
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
return $result;
}
?>
juan:clave
1Connection closed by foreign host
......................................................
Para acceder a un servidor de News Usenet, se requiere usar un protocolo especifico, el NNTP,
Network News Transfer Protocol.
Este protocolo está muy bien definido en el RFC977 (Request For Comment numero 977),
que se encuentra en http://www.w3.org/Protocols/rfc977/rfc977.html
Este documento describe con precisión como conectarse y hablar con un servidor NNTP,
Autor: Ing. Oscar R. Espeche
67
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
¿Cómo conectar?
Para conectar con un servidor NNTP necesitamos saber su hostname o dirección IP, y el
puerto en el que el servidor está corriendo. Deberíamos incluir el timeout, de forma que una
llamada errónea, no nos cuelgue la aplicación.
<?php
$cfgServer = "your.news.host";
$cfgPort = 119;
$cfgTimeOut = 10;
// open a socket
if(!$cfgTimeOut)
// sin timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort);
else
// con timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);
if(!$usenet_handle) {
echo "Falló la conexión con USENET\n";
exit();
}
else {
echo "Conectado con USENET\n";
$tmp = fgets($usenet_handle, 1024);
}
?>
Ya estamos conectados al servidor, y podemos hablar con él a través del socket abierto.
Supongamos que queremos bajar 10 artículos de algún grupo de noticias (news). RFC977
indica que lo primero que hay que hacer es seleccionar el grupo de noticias con el comando
GROUP:
GROUP ggg
El parámetro ggg es el nombre del grupo de noticias que seleccionamos (por ejemplo:
es.comp.os.linux.programacion).
Un listado de los grupos de noticias disponibles, se puede conseguir con el comando LIST. La
respuesta del servidor nos indicará el número del primer y último artículo del grupo, y una
estimación de los artículos disponibles.
Ejemplo:
Trying aa.bb.cc.dd...
Connected to my.news.host.
Escape character is '^]'.
200 my.news.host InterNetNews NNRP server
INN 2.2.2 13-Dec-1999 ready (posting ok).
GROUP es.comp.os.linux.programacion
211 232 222996 223235 es.comp.os.linux.programación
quit
205 .
Hay que prestar atención al hecho de que el servidor puede requerir autenticación antes de
seleccionar el grupo de news, dependiendo de si es público o privado. Incluso puede dejar
libre acceso a la lectura de artículos, pero necesitar autorización para publicar nuevos
artículos.
<?php
//$cfgUser = "xxxxxx";
//$cfgPasswd = "yyyyyy";
$cfgNewsGroup = "alt.php";
// check error
// seleccionar el newsgroup
?>
Descargando artículos
Ahora que sabemos cuál es el número del último artículo disponible, es fácil bajarse los 10
últimos artículos. RFC977 dice que el comando ARTICLE puede ser usado con el número de
artículo, o bien, con el ID del Mensaje.
No es lo mismo una cosa que otra. El primero es un índice que utiliza el servidor de news al
que nos conectamos, y el segundo es un índice universal que representa al artículo en todos
los servidores NNTP. El ID del mensaje es un número que encontramos en la cabecera del
mensaje.
<?php
$cfgLimit = 10;
$bucle=$last-$cfgLimit;
set_time_limit(0);
$article="";
$tmp = fgets($usenet_handle, 4096);
if(substr($tmp,0,3) != "220") {
echo "+----------------------+\n";
echo "Error en artículo $bucle\n";
echo "+----------------------+\n";
}
else {
while($tmp!=".\r\n") {
$tmp = fgets($usenet_handle, 4096);
$article = $article.$tmp;
}
echo "+----------------------+\n";
echo "Artículo $bucle\n";
echo "+----------------------+\n";
echo "$article\n";
}
$bucle++;
}
?>
Así, habremos bajado los 10 últimos artículos de este grupo de noticias en este servidor. Es
posible descargar sólo la cabecera de los artículos, usando el comando HEAD, o sólo el
contenido, usando el comando BODY.
Cerrando la Conexión
Para finalizar la sesión con el servidor NNTP, simplemente cerramos el socket usando fclose(),
igual que si cerráramos un archivo.
<?php
// cierre de la conexión
fclose($usenet_handle);
?>
Vamos a empezar por definir un diagrama para realizar la autentificación de usuario en unas
páginas web, que nos servirá para programar luego las páginas ajustándose al diagrama.
En la imagen anterior podemos ver el diagrama, que empieza por la página donde se pide un
usuario y contraseña para acceder a la aplicación de acceso restringido.
Esta página la he dibujado con línea de puntos porque no es una página donde use el
navegador para nada, sino que sólo es una página de paso que redirecciona a un sitio u otro
dependiendo de los datos que reciba.
proteger con usuario contraseña, debe de realizar unas comprobaciones de seguridad para
saber si se ha pasado con éxito el proceso de autentificación o si se está intentando acceder
de manera no permitida a esa página. Esta comprobación la he dibujado como una capa con
color verde más oscuro sobre la página de la aplicación. Si no se satisface dicha comprobación
(el usuario no se ha autentificado correctamente) se vuelve a la página donde escribir el
usuario y la contraseña.
Este es el esquema básico, que espero que se entienda bien. Ahora, veamos algunas
preguntas que podría hacerse el lector.
Podría ser que alguien conociese la URL de la aplicación de acceso restringido y la escribiese
directamente sobre la barra de direcciones del explorador, así que hacemos esta
comprobación para saber que realmente no se está accediendo sin pasar por la página que
comprueba si el usuario/contraseña es correcto
¿Cómo sabemos que ciertamente se ha pasado por la página que comprueba los
datos de autentificación?
Esta comprobación la podríamos hacer de varias maneras, así pues, depende de nuestro script
de autentificación y el nivel de seguridad que tratemos de implementar. Un ejemplo simple
podría ser crear una variable de sesión en la página que comprueba los datos, si es que eran
correctos, y en capa se seguridad de las páginas de acceso restringido comprobaríamos si esa
sesión está o no definida.
Pues de diversas maneras, para empezar, el historial de los computadores guarda las URL a
las que se ha accedido y cualquier persona podría recuperar la URL de nuestra aplicación con
acceso restringido. También se podría probar distintas URL que podríamos imaginarnos como
posibles para la aplicación y esperar a acertar con el nombre de archivo en algún momento,
incluso esta tarea se la podríamos encomendar a un programa para realizar muchas más
pruebas. En cualquier caso, nuestra seguridad no se puede quedar en simplemente que los
posibles intrusos no conozcan la dirección de la página.
Diagrama de flujo
Veremos el diagrama en donde se muestra la secuencia de las operaciones y las páginas que
intervienen.
Autor: Ing. Oscar R. Espeche
73
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Página XX
(pagina.php)
Aplicación Preotegida
(aplicación.php
seguridad.php)
NO
Formulario para autorizar
(index1.php) Autorizado ?
Nombre y clave
SI
Verificación
(control.php) Aplicación protegida
(Sigue en la aplicación y
Accede a los rec. protegidos)
Correcto ?
Salir de la aplicación
NO
SI
Autorizar
Activar sesión
Cierra sesión
(salir.php)
Para realizar esta página, utilizaremos HTML básico, excepto en una comprobación que nos
permitirá saber si se accede al formulario de nuevo por no haber introducido correctamente el
usuario y contraseña, pues, en ese caso, habría que mostrar un cartelito informando que el
usuario o la contraseña no son válidos.
El formulario tiene el atributo action dirigido hacia la página "control.php", que es la que se
encarga de recoger los datos y ver si son correctos.
Esta página será encargada de decidir si los datos de configuración son correctos y actuar en
consecuencia. Dependiendo del nivel de seguridad que queramos aplicar a nuestra aplicación,
esta página será más o menos complicada.
En un principio no deseo complicar mucho las cosas, así que explicaré una versión muy
reducida de este archivo de control, en la que se comprueba si el usuario y contraseña sean
dos valores específicos. Esto tiene la desventaja que sólo podemos crear un
usuario/contraseña distinto y no un sistema que permita muchos usuarios distintos. Bueno, en
realidad si que permitirá que accedan muchos usuarios a la vez, pero utilizando todos el
mismo nombre de usuario y contraseña.
En aplicaciones más avanzadas tendremos en una base de datos una lista de usuarios con sus
contraseñas. Entonces, en este archivo de control deberíamos hacer una búsqueda para ver si
existe una correspondencia en la base de datos de ese usuario con esa contraseña. Esto lo
veremos en adelante, ahora nos quedamos con la versión reducida.
Si los datos son correctos, se definirá una variable de sesión que servirá para saber que ese
visitante ha sido validado correctamente y tiene permiso para acceder a la aplicación. Además
redireccionará al visitante a la página de la aplicación restringida.
<?
//vemos si el usuario y contraseña es válido
if ($_POST["usuario"]=="juan" && $_POST["contrasena"]=="clave"){
//usuario y contraseña válidos
//defino una sesión y guardo datos
session_start();
session_register("autentificado");
$autentificado = "SI";
Este archivo, en nuestro caso llamado seguridad.php, se encargará de dotar seguridad a toda
la aplicación de acceso restringido. La técnica que vamos a utilizar es incluirlo al principio de
todas las páginas que queramos que permitan un acceso restringido.
Dependiendo del nivel de seguridad que deseemos implementar, la creación de este archivo
puede ser más o menos complicada. Como no deseo complicar en un principio los scripts, esta
versión resultará bastante sencilla.
Lo único que haré será recuperar la variable de sesión donde guardo si ese usuario ha sido
autentificado o no. Luego se comprueba esa variable para saber si se ha autentificado el
usuario o no, realizando estas acciones:
Si se había autentificado, no hago nada. Ni tan siquiera trato este caso, de modo que se
seguiría ejecutando la página con el contenido que correspondiese. No hay que olvidar que
este archivo de seguridad se va a ejecutar como un include al principio de todos los archivos
de la aplicación restringida, lo que significa que, si no se hace nada, se seguiría mostrando la
página donde este archivo está incluido.
<?
//Inicio la sesión
session_start();
La aplicación con acceso restringido se realizará como cualquier otra aplicación de PHP, con la
salvedad de que, a todos los archivos que queramos proteger, habrá que incluirles al principio
la capa de seguridad, representada por el archivo seguridad.php.
Como decía, todo en el archivo de la aplicación se realizará como cualquier otro archivo de
PHP, es decir, con sólo incluir el módulo de seguridad, el archivo ya tendrá el acceso
restringido y todo lo demás lo haremos de manera transparente a este estado de seguridad.
<?include ("seguridad.php");?>
<html>
<head>
<title>Aplicación segura</title>
</head>
<body>
<h1>Si estás aquí es por que te has autentificado</h1>
<br>
----
<br>
Aplicación segura
<br>
----
<br>
<br>
<a href="salir.php">Salir</a>
</body>
</html>
Un detalle que hemos incluido es un enlace para salir de la aplicación, que se dirige a el
archivo salir.php.
una sesión y que se marche de la aplicación segura sin cerrar la sesión, con lo que quedaría
abierta para que cualquier otra persona que siga con la sesión anterior, pueda acceder a la
aplicación volviendo por el historial de páginas del navegador.
Las sesiones se finalizan solas cuando pasa un determinado tiempo sin recibir nuevas
peticiones, pero no deseamos que antes de que se finalicen se pueda acceder con ese
computador a nuestra aplicación restringida.
El archivo en concreto lo único que hace es terminar la sesión asociada a su acceso. Podemos
ver el código a continuación.
<?
session_start();
session_destroy();
?>
<html>
<head>
<title>Has salido!!</title>
</head>
<body>
Gracias por tu acceso
<br>
<br>
<a href="index.php">Ir al formulario de autentificación</a>
</body>
</html>
Se muestra el código que se usó para realizar las operaciones que se indicaron en el diagrama
de flujo.
Pagina.php
<p>
bla..bla...
Autor: Ing. Oscar R. Espeche
79
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<p>
bla..bla...
<p>
bla..bla...
<p>
<p>
bla..bla...
<p>
bla..bla...
<p>
bla..bla...
<p>
bla..bla...
aplicación.php
<?include ("seguridad.php");?>
<html>
<head>
<title>Aplicación segura</title>
</head>
<body>
<h1>Si estás aquí es por que te has autentificado</h1>
<br>
----
<br>
Aplicación segura
<br>
----
<br>
<br>
<a href="salir.php">Salir</a>
</body>
</html>
Salir.php
<?
session_start();
session_destroy();
?>
<html>
<head>
<title>Has salido!!</title>
</head>
<body>
Gracias por tu acceso
<br>
<br>
<a href="pagina.php">Ir a la pagina no protegida</a>
</body>
</html>
Index1.php
<html>
<head>
<title>Sistema de autentificación</title>
</head>
<body>
<h1>Autentificación PHP</h1>
<form action="control.php" method="POST">
<table align="center" width="225" cellspacing="2" cellpadding="2" border="0">
<tr>
<td colspan="2" align="center"
<?if ($_GET["errorusuario"]=="si"){?>
bgcolor=red><span style="color:ffffff"><b>Datos incorrectos</b></span>
<?}else{?>
bgcolor=#cccccc>Introduce tu clave de acceso
<?}?></td>
</tr>
<tr>
<td align="right">USUARIO:</td>
<td><input type="Text" name="usuario" size="8" maxlength="50"></td>
</tr>
<tr>
Autor: Ing. Oscar R. Espeche
81
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<td align="right">PASSWORD:</td>
<td><input type="password" name="contrasena" size="8" maxlength="50"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="Submit" value="ENTRAR"></td>
</tr>
</table>
</form>
<br>
<br>
<a href="pagina.php">Volver</a>
</body>
</html>
Cntrol.php
<?
//vemos si el usuario y contraseña es válido
if ($_POST["usuario"]=="juan" && $_POST["contrasena"]=="clave"){
//usuario y contraseña válidos
//defino una sesión y guardo datos
session_start();
session_register("autentificado");
$autentificado = "SI";
Seguridad.php
<?
//Inicio la sesión
session_start();
Vamos a ver las páginas PHP que necesitaríamos para realizar un acceso restringido por clave
y contraseña para múltiples usuarios, donde cada uno tenga unos datos de acceso propios.
La base de datos
La base de datos que vamos a utilizar contendrá una tabla para los usuarios, donde cada uno
dispondrá, al menos, de dos campos: un nombre de usuario y una contraseña, los dos de tipo
texto.
Tabla usuario
Nombre del campo Tipo del campo
nombre Varchar(100)
clave Varchar(100)
En una base de datos de usuarios, el nombre de usuario debería ser un valor único, irrepetible
para otro usuario, es decir, no podremos tener dos usuarios con el mismo nombre. Por esta
razón, el campo nombre podría ser la clave principal de la tabla, aunque también podríamos
haber creado un campo adicional, llamado por ejemplo id_usuario, de tipo auto-numérico y
colocarlo como clave principal.
Para conseguir no insertar dos usuarios con el mismo nombre de usuario, a la hora de
insertarlos en la tabla, comprobaremos que no haya ningún usuario ya introducido con el
nombre de usuario que se pretende insertar. Este paso, aunque importante, no lo vamos a
ver, pues sólo nos vamos a centrar en decidir si un usuario puede entrar o no en la aplicación,
suponiendo que los usuarios se encuentran ya insertados en la base de datos.
En el ejemplo suponemos que utilizamos una base de datos MySQL, sin embargo, cualquier
tipo de base de datos podrá servir para unos objetivos como los que nos proponemos.
El script que se utilizará para decidir si un usuario puede o no entrar en la aplicación es muy
sencillo. Simplemente hace una llamada a la base de datos para comprobar si los datos de
Autor: Ing. Oscar R. Espeche
83
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
autentificación escritos por el visitante (usuario y contraseña) corresponden con los de algún
usuario. En caso de que así sea, se permite la entrada y de no ser así, se deniega.
Lo primero sería abrir una conexión con la base de datos y seleccionar la base con la que
hemos de trabajar.
Un segundo paso es construir una sentencia SQL que nos permita comprobar si existe o no un
usuario con los datos de autentificación introducidos. Utilizamos una simple sentencia SELECT,
sobre la tabla de usuarios, donde se extraen usuarios que tengan el mismo nombre de usuario
y la contraseña introducidos en la página de acceso.
//Ejecuto la sentencia
$rs = mysql_query($ssql,$conn);
Si esa sentencia SELECT responde con algún registro encontrado, sabremos que existe un
usuario donde sus datos de autentificación corresponden perfectamente con los introducidos.
En ese caso podremos realizar las acciones encaminadas a permitir el acceso. Por el contrario,
si la sentencia SELECT no encuentra ningún registro, sabremos que no existe un usuario con
los datos de autentificación introducidos y por lo tanto, deberemos realizar las acciones
encaminadas a restringir el acceso.
if (mysql_num_rows($rs)!=0){
//usuario y contraseña válidos
//defino una sesión y guardo datos
session_start();
session_register("autentificado");
$autentificado = "SI";
header ("Location: aplicacion.php");
}else {
//si no existe le mando otra vez a la portada
header("Location: index.php?errorusuario=si");
}
Las acciones para restringir o permitir el acceso son exatamente iguales a las que veníamos
Autor: Ing. Oscar R. Espeche
84
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
utilizando en el script de control sin utilizar la base de datos. Así que no vamos a comentarlas
más, sino que nos referimos al artículo donde las explicamos.
El código completo del ejemplo sería el siguiente. Reeemplazaría al código que vimos
anteriormente.
Control.php
<?
$usuario= $_POST["usuario"];
//$usuario= "juan";
//$contrasena= "clave";
$contrasena=$_POST["contrasena"];
//Sentencia SQL para buscar un usuario con esos datos
$ssql = "SELECT * FROM usuarios WHERE usuario='".$usuario."' and clave ='".$contrasena."'";
//echo $ssql;
//exit;
//Ejecuto la sentencia
$rs = mysql_query($ssql,$conn);
if (mysql_num_rows($rs)!=0){
//usuario y contraseña válidos
//defino una sesion y guardo datos
session_start();
session_register("autentificado");
$autentificado = "SI";
header ("Location: aplicacion.php");
}else {
//si no existe le mando otra vez a la portada
header("Location: index1.php?errorusuario=si");
}
mysql_free_result($rs);
mysql_close($conn);
?>
Nota: Es importante destacar que esta página no debería contener ningún tipo de texto antes
de la apertura de código PHP, ni tan siquiera saltos de línea. Esto es debido a que al final se
realiza una redirección y este tipo de instrucciones solamente se puede ejecutar si no se ha
escrito todavía ningún carácter en el cuerpo.
Este calendario, por si sólo, no tiene mucha utilidad, pero lo podremos utilizar para cualquier
cosa que necesitemos, por ejemplo una aplicación que implemente una agenda o, en general,
cualquier caso en el que queramos que el usuario seleccione una fecha.
La aplicación calendario va a componerse por tres archivos, podía hacerse en uno, pero así
creemos que resulta más claro a la hora de documentar y posteriormente, de utilizar en otras
aplicaciones.
• Página índice, index.php, donde el usuario accederá para ver el calendario.
• Librería de funciones, calendario.php. Con varias funciones que vamos a utilizar
dentro de la aplicación. Estará la función mostrar_calendario() y otras funciones de
manejo de fechas. Esta librería es el elemento "portable" que podremos utilizar el otras
aplicaciones.
• Hoja de estilos, estilos.css. Esta hoja de estilos nos permitirá definir la forma del
calendario, es decir, el tipo de letra, los colores, etc. Si se desea cambiar estos estilos
solamente debería actualizar esta declaración CSS.
Lo que va a hacer este archivo, la primera vez que se accede, es mostrar el calendario del año
y mes actuales. Posteriormente, el usuario puede cambiar el mes o año del calendario a través
de los enlaces o el formulario disponibles para tal efecto. En éste caso, se accederá otra vez al
archivo índice pasándole por POST o GET el nuevo mes y año que ha de mostrar.
El código es el siguiente.
<html>
<head>
<title>Calendario PHP</title>
<link rel="STYLESHEET" type="text/css" href="estilo.css">
Autor: Ing. Oscar R. Espeche
87
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
</head>
<body>
<div align="center">
<?
require ("calendario.php");
mostrar_calendario($mes,$ano);
formularioCalendario($mes,$ano);
?>
</div>
</body>
</html>
Para empezar nos fijamos que en la cabecera, concretamente en la etiqueta <link> se incluye
el archivo estilo.css como una declaración de archivos externa. No vamos a comentar aquí la
hoja de estilos, que se puede ver en el tema dedicado a la misma.
Lo primero, se incluye, con la función require() de PHP, la librería calendario, que suponemos
que está en el mismo directorio que el archivo índice. Require es una función que sirve para
incrustar dentro de un archivo PHP el texto o código de otro archivo. Al incrustar nuestra
librería de funciones dentro del script index.php tenemos perfectamente disponibles todas las
funciones de calendario.php.
Luego, con el if que se puede ver a continuación, se comprueba si ha venido algo por POST o
por GET.
• En caso de que no venga nada por POST ni GET se obtiene el instante actual con un
Timestamp Unix y lo utilizamos para extraer el mes y el año con la función date().
• En caso de que recibamos por POST o GET algún dato inicializamos las variables mes y
año a lo que se está recibiendo.
Autor: Ing. Oscar R. Espeche
88
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Vamos a construir una función que crea el calendario de un mes y un año determinados. Por
ejemplo, si indicamos que se cree el calendario de febrero de 2004, obtendríamos algo como
lo que se puede ver en la imagen.
Este ejemplo presenta una ligera complejidad, aunque esperamos que con las explicaciones se
pueda entender cómo hemos resuelto el problema.
Función mostrar_calendario($mes,$ano)
Empezaremos escribir el mes y año que se están visualizando. Nos debemos fijar que a los
lados del mes y año tenemos unas flechitas para ir al mes anterior o siguiente. Estas flechitas
son enlaces al índice en los que pasamos por parámetro el mes y año que debe visualizarse.
Vemos el código del encabezado y lo comentamos más adelante.
align=center class=tit>";
Escribo la cabecera de la tabla, indicando el mes y el año que vamos a imprimir en la página.
Para empezar utilizamos una función que devuelve el nombre de un mes en castellano.
Autor: Ing. Oscar R. Espeche
90
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Seguimos por colocar un poco de código HTML, sin más importancia. Luego calculamos el mes
y año anterior para colocarlo en el enlace que habíamos comentado con las flechita hacia
atrás.
El código que inserta el enlace ser puede ver en la siguiente línea. Su atributo href tiene el
valor index.php?nuevo_mes=$mes_anterior&nuevo_ano=$ano_anterior, donde podemos
observar que efectivamente se llama a index.php pasando los valores del mes y año a
mostrar.
Luego imprimimos en la página el valor del mes y año y en las siguientes líneas podemos ver
cómo se obtiene el mes y año siguientes para hacer la correspondiente flechita-enlace, de
manera similar a como se hizo anteriormente.
Este trozo de código sirve para escribir la siguiente fila de la tabla, con las iniciales de los días
de la semana, desde el lunes al domingo.
Para continuar, vamos a empezar a escribir los números de los días, del 1 hasta el número de
días que tenga el mes. Habrá que empezar, lógicamente, por el día 1, pero antes de escribirlo,
debemos averiguar qué día de la semana es el día 1. Si se tratase de un viernes, por ejemplo,
deberíamos dejar, en la primera fila, libres las casillas del lunes al jueves y a partir de del
viernes empezar a colocar números de días.
Vamos a llevar la cuenta del día que tenemos que imprimir en pantalla con la variable
$dia_actual.
También tenemos que crear una variable que valga el número de días que tiene el mes, para
saber cuándo parar de escribir números en el calendario.
Estas serían las siguientes líneas de código para obtener todos los datos de control que
estamos señalando.
• Calcula_numero_dia_semana() para obtener el día de la semana del primer día del mes.
• UltimoDia(), para saber cuantos días tiene el mes.
Ahora tenemos toda la información necesaria para escribir la primera fila de días en el
calendario. Recordar que varias de las casillas de esta fila deben aparecer vacías porque el
mes no tiene por qué empezar en lunes.
Vemos que no encierra ningún misterio, simplemente hacemos un bucle que se repetirá 7
veces, tantas como días de la semana. Dentro del bucle comprobamos si el día de la semana
actual es menor que $numero_dia, donde guardábamos el número de la semana del primer
día del mes.
Si no hay que escribir el día simplemente se coloca la celda vacía y si tengo que escribirlo se
coloca el día actual en la celda y se incrementa en uno dicho día actual.
Autor: Ing. Oscar R. Espeche
92
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
Para continuar con el resto de las semanas, debemos escribir en el calendario todos los demás
días del mes, continuando por donde lo hubiésemos dejado. Para ello utilizamos un simple
bucle que recorre esos días mientras que no lleguemos al último día del mes.
La única complejidad que puede tener este trozo de código es saber cuándo debemos escribir
el principio y el final de la fila, con sus correspondientes <tr> y </tr>. Para éllo, vamos a
llevar la cuenta, con $numero_dia, del día de la semana que estamos imprimiendo.
Entre medias de cada iteración se incrementa el $día_actual (que lleva la cuenta de todos los
días del mes) y el $numero_día (que indicábamos que servía para saber en qué parte de la fila
estamos).
//compruebo que celdas me faltan por escribir vacías de la última semana del mes
for ($i=$numero_dia;$i<7;$i++){ //si no se completó la última semana $i es <7
echo "<td></td>"; //celdas vacías
}
Simplemente escribo celdas vacías para las últimas casillas de la semana que acaba el mes
donde no quedan días. Igual que al principio del calendario el primer día no tenía que estar en
la primera casilla, el último día del calendario no tiene porque estar en la última casilla
disponible.
Esta función sirve para imprimir en pantalla el formulario que utilizamos para seleccionar
cualquier otro mes y año que deseemos visualizar en la página. No debería significar un
problema muy gordo, pues se trata de un simple formulario. Lo único que complica un poco el
código es que deseamos que el formulario presente inicialmente los valores de mes y año que
está mostrando el calendario, pero veremos rápido cómo hacerlo.
Para empezar, vemos que la función recibe el mes y el año, que nos servirá para saber el valor
por defecto a mostrar en nuestro formulario. El código lo podemos ver por partes a
continuación.
echo '
<table align="center" cellspacing="2" cellpadding="2" border="0">
<tr><form action="index.php" method="POST">';
Con esto imprimimos por pantalla la cabecera de la tabla donde vamos a alojar el formulario y
la cabecera del propio formulario. Nos fijamos que el atributo action del formulario lo tenemos
dirigido hacia el archivo índice.
echo ' <td align="center" valign="top"> Mes: <br> <select name=nuevo_mes> <option
value="1"';
Estas líneas de código sirven para escribir el <select> correspondiente al mes. Lo único que lo
hace complicado es precisamente el hecho de que tenemos que comprobar si el mes que se
va a imprimir es el mes que está mostrando el calendario, pues en ese caso deberíamos
marcar como selected el <option> correspondiente. Esto se hace con los sucesivos if que hay
insertados entre cada etiqueta <option>.
echo '
<td align="center" valign="top">
Año: <br>
<select name=nuevo_ano>
<option value="2002" ';
if ($ano==2002)
echo "selected";
echo' >2002
<option value="2003" ';
if ($ano==2003)
echo "selected";
echo '>2003
<option value="2004" ';
if ($ano==2004)
echo "selected";
echo '>2004
<option value="2005" ';
if ($ano==2005)
echo "selected" ;
echo '>2005
<option value="2006" ';
if ($ano==2006)
echo "selected" ;
echo '>2006
</select>
</td>';
De manera parecida a como se ha realizado para los meses, se escribe también el año,
comprobando en cada ocasión si el año que se va a escribir corresponde con el del calendario.
En este ejemplo ponemos años desde el 2002 al 2006
echo '
</tr>
<tr>
<td colspan="2" align="center"><input type="Submit" value="[ IR A ESE MES ]"></td>
</tr>
</table><br>
<br>
</form>';
Para acabar mostramos el botón de submit del formulario y las etiquetas de cierre de tabla y
formulario.
A continuación explicaremos las funciones que venimos utilizando para la creación del
calendario, que se encuentran dentro de la librería calendario.php, al igual que las funciones
de mostrar_calendario() y formularioCalendario().
Función calcula_numero_dia_semana($dia,$mes,$ano)
Esta función calcula el número de día de la semana de una fecha indicada por parámetro. El
número de día de la semana que devuelve corresponde con 0 en el caso de que la fecha sea
un lunes, 1 en caso de ser martes, y así hasta llegar al 6, que corresponde con el domingo.
La fecha la recibe la función con el valor del día, mes y año, pasado en variables
independientes. El código es el siguiente:
function calcula_numero_dia_semana($dia,$mes,$ano){
$numerodiasemana = date('w', mktime(0,0,0,$mes,$dia,$ano));
if ($numerodiasemana == 0)
$numerodiasemana = 6;
else
$numerodiasemana--;
return $numerodiasemana;
}
Primero obtenemos el número de día de la semana que nos ofrece PHP a través de la función
date(). Como PHP, al igual que la mayoría de los sistemas, está pensado en inglés, y para él,
el numero de la semana correspondiente a domingo es el 0, el del lunes es el 1. Por eso
tenemos unas líneas de código para convertir el número de la semana del "inglés al español".
Función ultimoDia($mes,$ano)
Sirve para devolver el último día de un mes y año indicados por parámetro. El último día del
mes se refiere al número de días que tiene un mes. Por ejemplo en enero 31, febrero 28 ó 29,
... diciembre 31.
function ultimoDia($mes,$ano){
$ultimo_dia=28;
while (checkdate($mes,$ultimo_dia + 1,$ano)){
$ultimo_dia++;
}
return $ultimo_dia;
}
Para hallar ese dato vamos a utilizar una pequeña treta que consiste en suponer que el mes
tiene 28 días como mínimo y empezar a validar cada uno de los días siguientes hasta que la
fecha que estamos construyendo sea incorrecta. En ese caso querrá decir que el número de
días es 1 menos que los que tenemos en el momento de fallar la fecha.
Por ejemplo, para enero, empezaríamos por 28. Entonces validamos el día siguiente (29).
Como es correcta la fecha "29 de enero de una año cualquiera", acumulamos 1 en la variable
$ultimo_dia para situarnos en esa fecha válida. Posteriormente, validamos el 30 de enero, que
también es correcta, entonces volvemos a acumular 1 en la variable para situarnos en esa
nueva fecha correcta... así hasta que intentemos validar la fecha "32 de enero" que será la
primera que falle. Entonces paramos el bucle y dejamos de acumular a la fecha que teníamos,
que era válida. Esto funciona bien para cualquier mes, incluso para febrero, sea el año bisiesto
o no.
Función dame_nombre_mes($mes)
Devuelve el nombre del mes que recibe como número en el parámetro. Ejemplo sencillo donde
los haya, sólo tiene una estructura switch que asigna un mombre de mes para cada valor del
parámetro.
function dame_nombre_mes($mes){
switch ($mes){
case 1:
$nombre_mes="Enero";
break;
case 2:
$nombre_mes="Febrero";
break;
case 3:
$nombre_mes="Marzo";
break;
case 4:
$nombre_mes="Abril";
break;
case 5:
$nombre_mes="Mayo";
break;
case 6:
$nombre_mes="Junio";
break;
case 7:
$nombre_mes="Julio";
break;
case 8:
$nombre_mes="Agosto";
break;
case 9:
$nombre_mes="Septiembre";
break;
case 10:
$nombre_mes="Octubre";
break;
case 11:
$nombre_mes="Noviembre";
break;
case 12:
$nombre_mes="Diciembre";
break;
}
return $nombre_mes;
}
Con esto hemos acabado el ejercicio del calendario simple con PHP. Aunque seguro que habrá
hecho falta un esfuerzo por vuestra parte, esperamos que las explicaciones hayan sido
suficientes y se haya entendido bien.
index.php
<html>
<head>
<title>Calendario PHP</title>
</head>
<body>
<div align="center">
<?
require ("calendario.php");
$tiempo_actual = time();
}else {
$mes = $nuevo_mes;
$ano = $nuevo_ano;
mostrar_calendario($mes,$ano);
formularioCalendario($mes,$ano);
?>
</div>
</body>
</html>
calendario.php
<?
function calcula_numero_dia_semana($dia,$mes,$ano){
$numerodiasemana = date('w', mktime(0,0,0,$mes,$dia,$ano));
if ($numerodiasemana == 0)
Autor: Ing. Oscar R. Espeche
100
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
$numerodiasemana = 6;
else
$numerodiasemana--;
return $numerodiasemana;
}
//función que devuelve el último día de un mes y año dados
function ultimoDia($mes,$ano){
$ultimo_dia=28;
while (checkdate($mes,$ultimo_dia + 1,$ano)){
$ultimo_dia++;
}
return $ultimo_dia;
}
function dame_nombre_mes($mes){
switch ($mes){
case 1:
$nombre_mes="Enero";
break;
case 2:
$nombre_mes="Febrero";
break;
case 3:
$nombre_mes="Marzo";
break;
case 4:
$nombre_mes="Abril";
break;
case 5:
$nombre_mes="Mayo";
break;
case 6:
$nombre_mes="Junio";
break;
case 7:
$nombre_mes="Julio";
break;
case 8:
$nombre_mes="Agosto";
break;
case 9:
$nombre_mes="Septiembre";
break;
case 10:
$nombre_mes="Octubre";
break;
case 11:
$nombre_mes="Noviembre";
break;
case 12:
$nombre_mes="Diciembre";
break;
}
return $nombre_mes;
}
function mostrar_calendario($mes,$ano){
//tomo el nombre del mes que hay que imprimir
$nombre_mes = dame_nombre_mes($mes);
$ano_anterior = $ano;
if ($mes_anterior==0){
$ano_anterior--;
$mes_anterior=12;
}
echo "<a style=color:white;text-decoration:none
href=index.php?nuevo_mes=$mes_anterior&nuevo_ano=$ano_anterior><<</a></td>";
echo "<td align=center class=tit>$nombre_mes $ano</td>";
echo "<td align=right style=font-size:10pt;font-weight:bold;color:white>";
//calculo el mes y ano del mes siguiente
$mes_siguiente = $mes + 1;
$ano_siguiente = $ano;
if ($mes_siguiente==13){
$ano_siguiente++;
$mes_siguiente=1;
}
echo "<a style=color:white;text-decoration:none
href=index.php?nuevo_mes=$mes_siguiente&nuevo_ano=$ano_siguiente>>></a></td></tr></table></td></tr>";
echo ' <tr>
<td width=14% align=center class=altn>L</td>
<td width=14% align=center class=altn>Ma</td>
<td width=14% align=center class=altn>Mi</td>
<td width=14% align=center class=altn>J</td>
<td width=14% align=center class=altn>V</td>
<td width=14% align=center class=altn>S</td>
<td width=14% align=center class=altn>D</td>
</tr>';
echo "</tr>";
}
}
//compruebo que celdas me faltan por escribir vacias de la última semana del mes
for ($i=$numero_dia;$i<7;$i++){
echo "<td></td>";
}
echo "</tr>";
echo "</table>";
}
function formularioCalendario($mes,$ano){
echo '
<table align="center" cellspacing="2" cellpadding="2" border="0">
<tr><form action="index.php" method="POST">';
echo '
<td align="center" valign="top">
Mes: <br>
<select name=nuevo_mes>
<option value="1"';
if ($mes==1)
echo "selected";
echo'>Enero
<option value="2" ';
if ($mes==2)
echo "selected";
echo'>Febrero
<option value="3" ';
if ($mes==3)
echo "selected";
echo'>Marzo
<option value="4" ';
if ($mes==4)
echo "selected";
echo '>Abril
<option value="5" ';
if ($mes==5)
echo "selected";
echo '>Mayo
<option value="6" ';
if ($mes==6)
echo "selected";
echo '>Junio
<option value="7" ';
if ($mes==7)
echo "selected";
echo '>Julio
<option value="8" ';
if ($mes==8)
echo "selected";
echo '>Agosto
<option value="9" ';
if ($mes==9)
echo "selected";
echo '>Septiembre
<option value="10" ';
if ($mes==10)
echo "selected";
echo '>Octubre
<option value="11" ';
if ($mes==11)
echo "selected";
echo '>Noviembre
Autor: Ing. Oscar R. Espeche
103
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
<br>
</form>';
}
estilo.css
BODY {
font-family : verdana,arial,helvetica;
font-size : 10pt;
background-color : #ffffff;
}
TD {
font-family : verdana,arial,helvetica;
font-size : 10pt;
}
INPUT {
font-family : verdana,arial,helvetica;
font-size : 8pt;
Autor: Ing. Oscar R. Espeche
104
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
}
TEXTAREA {
font-family : verdana,arial,helvetica;
font-size : 8pt;
}
SELECT {
font-family : verdana,arial,helvetica;
font-size : 8pt;
}
.altn {
font-family : verdana,arial,helvetica;
font-size : 10pt;
color: #ffffff;
background-color: #dbdbdb;
}
.tit {
font-family : verdana,arial,helvetica;
font-size : 10pt;
color: #ffffff;
background-color: #bbbbbb;
font-weight: bold;
}
Una librería de abstracción de los datos como ADODB es lo que se necesita si se desea
asegurar en gran medida la portabilidad de la aplicación. Provee una serie de funciones
comunes para comunicarse con las distintas bases de datos.
ADODB viene de " Active Data Objects DataBase" (no muy original pero efectivo).
ADODB actualmente soporta MySQL, PostgreSQL, Oracle, Interbase, Microsoft SQL Server,
Access, FoxPro, Sybase, ODBC y ADO. Puede obtener ADODB en:
http://sourceforge.net/project/showfiles.php?group_id=42718
Ejemplo MySQL
Tomaremos como referencia a nuestra ya conocida base MySQL para aprender un poco de
ADODB. Conectamos al server MySQL en localhost, a la base de datos midb, y ejecutamos
una sentencia SQL. El resultado es impreso en pantalla, una línea por cada fila obtenida.
Ejemplo_simple_mysql.php
<?
mysql_select_db("alumno1",$db);
print "<br>";
?>
ejemplo_simple_ADODB.php
include("adodb.inc.php");
$db = newADOConnection('mysql');
$db->Connect("localhost", "alumno1", "alumno", "alumno1");
$result = $db->Execute("SELECT * FROM tabla1");
if ($result == false) die("falló el acceso a la conexión");
while (!$result->EOF) {
for ($i=0, $max=$result->FieldCount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->MoveNext();
Autor: Ing. Oscar R. Espeche
108
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
print "<br>";
}
include("adodb.inc.php");
$db = NewADOConnection('mysql');
$db->Connect("localhost", "root", "password", "midb");
La conexión puede parecer algo más complicada que en MySQL pero se explica en que
ADODB es totalmente orientado a objetos. No es imprescindible conocer OOP porque todo
queda oculto en la función NewADOConnection() .
Para ahorrar memoria solo se cargan las funciones específicas de la base de datos que
vamos a utilizar. Cada driver tiene un archivo distinto que se carga mediante un include
automáticamente.
Una vez cargado el driver que vamos a utilizar mediante la función NewADOConnection() nos
conectamos a la base de datos usando $db->Connect().
Ejecutando SQL
Para enviar una sentencia sql al motor de base de datos se utiliza la función Execute(). Esta
función devuelve un objeto "recordset" si la ejecución fue correcta o un "false" si hubo algún
error.
Obteniendo datos
while (!$result->EOF) {
for ($i=0, $max=$result->FieldCount(); $i < $max; $i++)
Autor: Ing. Oscar R. Espeche
109
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL
El proceso para obtener datos es como el proceso para leer desde un archivo. Para cada
línea observamos si hemos llegado al final del archivo (EOF). Mientras no lleguemos al final
del archivo seguimos leyendo y moviéndonos a la siguiente línea (movenext).
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs1 = $db->Execute('select * from tabla');
Array asociativo:
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rs2 = $db->Execute('select * from tabla');
Como se ve en el ejemplo, los dos recorsets usan diferentes métodos para almacenar los
datos recuperados de la consulta usando $ADODB_FETCH_MODE (el seteo de
$ADODB_FETCH_MODE debe ser previo a Execute()).
ADOConnection
El objeto que realiza la conexión a la base de datos, ejecuta las sentencias SQL y tiene otro
set de funciones para estandarizar el formato de sentencias SQL como la concatenación de
cadenas o formatos de fechas.
rs2html($recordset) esta función genera una tabla HTML con el resultado del recordset.
include('adodb.inc.php');
include('tohtml.inc.php'); /* incluye la función rs2html */
$conn = &ADONewConnection('mysql');
$conn->PConnect('localhost','userid','password','database');
$rs = $conn->Execute('select * from tabla');
rs2html($rs); /* graba el recordset en una tabla HTML */
Inserts y Updates
Imagine que tenemos los siguientes datos para guardar en una base de datos.
$ID = 3
$Fecha = mktime(0,0,0,1,31,2004) /* 31 Enero 2004 */
$Nota = ’ hola Pepe’
El primer problema es que cada base de datos usa las fechas en un formato distinto. MySQL
espera YYYY-MM-DD como formato, otras bases de datos requieren otros formatos. ADODB
tiene una función que puede ayudarnos DBDate() que convierte una fecha en el formato
correcto para realizar updates o inserts.
La comilla simple del campo Note también es un problema. La función qstr() nos puede
ayudar en esto.
ADODB tiene también dos funciones que ayudan a reconocer si un insert update o delete
han sido correctos.
MetaTypes
Por Ejemplo:
Cada base de datos define sus columnas de una manera particular, ADODB tiene una función
especial para estandarizar los tipos de datos, MetaType($type, $max_length).
ADODB tiene una función que asegura la portabilidad de una sql en el tema de los límites de
un recordset, $connection->SelectLimit($sql,$nrows,$offset), en el caso de los productos
Microsoft se usará SELECT TOP, en mysql, postgresql se usará LIMIT y en otras bases de
datos que no lo soporten se emula.
Cacheo de consultas
ADODB permite cachear los resultados de las consultas SQL en función de un tiempo
definido. Las consultas deben entonces realizarse con
$connection->CacheExecute($secs_en_cache,$sql)
$connection->CacheSelectLimit($secs_en_cache,$sql,$nrows,$offset).
Los resultados se almacenan en un directorio que debe tener los permisos apropiados.
Conclusión
ADODB es lo suficientemente robusto y completo para casi cualquier aplicación. Está siendo
actualizado permanentemente y tiene muchos seguidores por lo que es una muy buena
opción.
Si está pensando en escribir software comercial en PHP y desea distribuirlo, debe considerar
ADODB. Está siendo usado con éxito, es LGPL, que significa que puede ser distribuido con
aplicaciones comerciales, dejando a su código propietario.
Otro ejemplo
<?
include('adodb.inc.php'); //Este es un archivo con los datos que necesita el programa para reconocer adodb
if (!$DB)
print "No se realizó la conexión";
else{
$query= "select * from tabla1";
$query.= "where nombre like '%$nombre%'";
for ($i=0;$i<=$numFilas;$i++){
$datos->Close(); //opcional
$conn->Close(); //opcional
}
?>