Vous êtes sur la page 1sur 114

PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

UNIVERSIDAD TECNOLÓGICA NACIONAL


Facultad Regional Córdoba

Secretaria de Extensión Universitaria

Área Tecnológica de Educación Virtual

Coordinador General de Educación Virtual: Magíster Leandro D. Torres

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

4-2 Sistema de encuestas

4-3 Contador de visitas acumuladas

4-4 Contando visitantes activos con PHP

4-5 Mandar mails desde PHP

4-6 Contactar con el visitante

4-7 Programando con sockets en PHP

4-8 Sistema de autentificación PHP para acceso a datos restringidos

4-9 Calendario con PHP

4-10 Abstracción de datos con ADODB

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.

Autor: Ing. Oscar R. Espeche


2
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-1 Libro de visitas con PHP y MySQL


Este ejercicio se puede seguir con unos conocimientos mínimos de PHP, de modo que está al
alcance de cualquier persona que se haya iniciado en este interesante lenguaje de
programación de páginas de servidor.

Esquema de funcionamiento del libro de visitas PHP

Veamos el diagrama de funcionamiento de la aplicación de libro de visitas en PHP para


hacernos una idea inicial, que completaremos más adelante con el código de cada script.

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.

1) Si no recibe datos del formulario:

Autor: Ing. Oscar R. Espeche


3
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Si existen más firmas, muestro el mensaje para verlas.

Si no existen más firmas, no hago nada.

Por último, coloco el formulario de firma para que los visitantes puedan participar.

2) Si recibo datos por el formulario:

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.

Si los datos eran correctos:

Si todas las comprobaciones fueron positivas, introduciremos los datos en el formulario y


daremos las gracias al visitante por firmar el libro.

Si los datos no eran correctos:

Advertiremos al visitante que debe rellenar los campos correctamente.

La base de datos MySQL del libro de visitas

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:

Autor: Ing. Oscar R. Espeche


4
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Nombre del campo Tipo


Id_librovisitas_php int(11)
nombre varchar(150)
email varchar(100)
valoracion tinyint(4)
comentario text

El campo id_librovisitas_php será un campo auto-numérico, que será la clave primaria de la


tabla. Los campos nombre y email serán de tipo cadena de texto, con 150 y 100 caracteres de
tamaño máximo respectivamente. El campo valoración guardará un número, en este caso de
tamaño pequeño (tinyint) porque sólo vamos a guardar números del 1 al 5. Por último el
comentario, que es una cadena de texto con longitud indeterminada.

La tabla la podremos crear en nuestro servidor de bases de datos con la siguiente sentencia
Crearte Table:

CREATE TABLE librovisitas_php (


id_librovisitas_php int(11) unsigned NOT NULL auto_increment,
nombre varchar(150) NOT NULL,
email varchar(100) NOT NULL,
valoracion tinyint(4),
comentario text,
PRIMARY KEY (id_librovisitas_php)
);

Mostrando las firmas del libro de visitas

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

Extraer las últimas firmas

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;

//ordeno la sentencia y limito el numero de resultados


$ssql .= " ORDER BY id_librovisitas_php desc limit 11";

//tomo el juego de resultados


$resultid = mysql_query($ssql,$conn);

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

En la última línea se ejecuta la sentencia SQL para extraer los datos.

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 bgcolor=cccccc colspan="2"><img src="images/pixeltrans.gif" width=1 height=1


border="0"></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

Autor: Ing. Oscar R. Espeche


7
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Mostrar el enlace de vermas


Al final de la página, si había más firmas por ver, hay que mostrar el enlace de vermas. Para
ello simplemente evaluamos la variable que contiene el puntero al registro actual. Si el bucle
anterior finalizó porque dicho puntero había llegado al final de la lista de valores, entonces es
que no hay más firmas que ver. Si por el contrario, el bucle finalizó y todavía quedaba alguna
firma en el puntero es que hay que mostrar el enlace de vermas y colocar el índice de la firma
que tocaría visualizar a continuación.

//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>";

Mostrar el formulario de firma

Por último se debería mostrar el formulario de la firma. Nosotros lo hemos separado en un


archivo aparte para que quede todo más organizado. En el código de nuestro ejercicio en esta
sección, lo único que encontraremos será el include con el archivo HTML que contiene el
formulario.

include ("formul_mensaje.html");

El formulario para firmar el libro de visitas

El código del formulario para que los visitantes puedan incluir su firma en el libro de visitas es
el siguiente.

<form name=librovisitas action="index.php" method="post">


<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class=titcol> <b>Firma el Libro de Visitas</b></td>
</tr>
<tr>
<td class=fuente8> Déjanos tu mensaje en el libro de visitas y danos tu opinión del sitio
<br>
<br>
</td>
</tr>
<tr>
<td>
Autor: Ing. Oscar R. Espeche
8
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

<table width="100%" cellspacing="0" cellpadding="0" border="0">


<tr>
<td class=fuente8 align="center">
Nombre
<br>
<input type="Text" name="nombre" size="20" maxlength="150">
<br>
<br>
Email
<br>
<input type="Text" name="email" size="20" maxlength="100">
<br>
<br>
Valoración
<br>
<select name="valoracion">
<option value=1>Repelente
<option value=2>Mal
<option value=3 selected>Regular
<option value=4>Bien
<option value=5>Fantástica
</select>
</td>
<td ALIGN=CENTER class=fuente8 valign="middle">
Comentarios:
<br>
<textarea name="comentario" cols="30" rows="7"></textarea>
</td>
</tr>
<tr>
<td colspan=2 align=center class=fuente8>
<br>
<input type="submit" value=" Enviar la firma al libro de visitas ">
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>

No reviste ninguna complicación para entenderlo. Simplemente deberemos conocer un poco la


forma de crear formularios HTML.

Autor: Ing. Oscar R. Espeche


9
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Comprobar si los datos recibidos son correctos

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.

Eliminar las etiquetas HTML o PHP

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.

//eliminamos las etiquetas HTML y PHP de las cadenas de texto


$nombre = strip_tags($_POST["nombre"]);
$email = strip_tags($_POST["email"]);
$comentario = strip_tags($_POST["comentario"]);

Cortamos las cadenas demasiado largas

Para no intentar introducir textos en la base de datos que en realidad no caben, recorto los
textos hasta su tamaño máximo.

//Cortamos las cadenas demasiado largas


$nombre=substr($nombre,0,150);
$email=substr($email,0,80);

Comprobamos que el visitante ha rellenado algo

Autor: Ing. Oscar R. Espeche


10
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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 no había rellenado nada mostramos un mensaje advirtiéndolo. En el caso contrario, es


decir, si todo era correcto, inserto en la base de datos la información.

Inserto los datos en la base de datos

Si todas las comprobaciones fueron correctas, se introduce en la base de datos del libro de
visitas la información recibida como firma.

Pero antes se realizará un pequeño ajuste adicional de los datos a introducir.

//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.

Autor: Ing. Oscar R. Espeche


11
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

//Generamos la ssql e insertamos el registro


$ssql = "INSERT INTO librovisitas_php (nombre,email,valoracion,comentario) VALUES ('" .
$nombre . "','" . $email . "'," . $_POST["valoracion"] . ",'" . $comentario . "')";
mysql_query($ssql,$conn);

Por último se muestra un mensaje dando las gracias al visitante que ha firmado el libro de
visitas.

<div align="center"><b>Muchas gracias por tu participación</b></div>

Nota: en una carpeta del sitio necesita colocar los archivos: Index.php, estilo.css,
formul_mensaje.htm,l que se detallan a continuación.

Autor: Ing. Oscar R. Espeche


12
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

createtable.txt

CREATE TABLE librovisitas_php (


id_librovisitas_php int(11) unsigned NOT NULL auto_increment,
nombre varchar(150) NOT NULL,
email varchar(100) NOT NULL,
valoracion tinyint(4),
comentario text,
PRIMARY KEY (id_librovisitas_php)
);

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:

C:\mysql\bin>mysql –u root –p(aquí va la clave)


use nombre_de_la_base;
CREATE TABLE librovisitas_php (
id_librovisitas_php int(11) unsigned NOT NULL auto_increment,
nombre varchar(150) NOT NULL,
email varchar(100) NOT NULL,
valoracion tinyint(4),
comentario text,
PRIMARY KEY (id_librovisitas_php)
);

Autor: Ing. Oscar R. Espeche


13
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y 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;
}

Autor: Ing. Oscar R. Espeche


15
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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";

//tomo el juego de resultados


$resultid = mysql_query($ssql,$conn);
?>

Aqu&iacute; puedes leer los mensajes de los visitantes y tambi&eacute;n puedes dejar el tuyo utilizando
el formulario de abajo.
<br>
<br>
<span class=fuente8><b>Muchas gracias por tu participaci&oacute;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

<? //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 bgcolor=cccccc colspan="2"><img src="images/pixeltrans.gif" width=1 height=1
border="0"></td></tr>
<td class=fuente8 valign="top">
<?echo strip_tags($damefila->comentario)?>
<td valign="top" align="right" nowrap class=fuente8>
Valoracion: <?echo $damefila->valoracion?>
</td>
</tr>
</table>

<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&aacute;s mensajes</a></b></div><br>";

//libero el conjunto de resultados


mysql_free_result($resultid);

//incluyo el formulario para firmar


include ("formul_mensaje.html");
}
else
{
//estoy recibiendo datos del fomulario de firmas
//Formateamos un poco el formulario, por si acaso los datos son incorrectos

//eliminamos las etiquetas HTML y PHP de las cadenas de texto


$nombre = strip_tags($_POST["nombre"]);
$email = strip_tags($_POST["email"]);
$comentario = strip_tags($_POST["comentario"]);

//Cortamos las cadenas demasiado largas


$nombre=substr($nombre,0,150);
$email=substr($email,0,80);

//Comprobamos que el visitante se ha molestado en rellenar algo


Autor: Ing. Oscar R. Espeche
17
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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&iacute;amos, no
obstante y si no resulta mucho esfuerzo, que rellenases alguno de los campos para dejar constancia de tu
visita.</div>
<?
}else{
//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";

//Generamos la ssql e insertamos el registro


$ssql = "INSERT INTO librovisitas_php (nombre,email,valoracion,comentario) VALUES ('" .
$nombre . "','" . $email . "'," . $_POST["valoracion"] . ",'" . $comentario . "')";
//echo $ssql . "<p>";
mysql_query($ssql,$conn);
?>
<div align="center"><b>Muchas gracias por tu participaci&oacute;n</b></div>
<?
}
?>
<br>
<br>
<div align="center"><b><a href=".">Volver al libro de visitas</a></b></div>
<?
}
mysql_close($conn);
?>
</td>
</tr>
</table>
<br>
</body>
</html>

Autor: Ing. Oscar R. Espeche


18
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Formul_mensaje.html

<form name=librovisitas action="index.php" method="post">


<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class=titcol>&nbsp;<b>Firma el Libro de Visitas</b></td>
</tr>
<tr>
<td class=fuente8>&nbsp;D&eacute;janos tu mensaje en el libro de visitas y danos tu opini&oacute;n del
sitio
<br>
<br>
</td>
</tr>
<tr>
<td>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class=fuente8 align="center">
Nombre
<br>
<input type="Text" name="nombre" size="20" maxlength="150">
<br>
<br>
Email
<br>
<input type="Text" name="email" size="20" maxlength="100">
<br>
<br>
Valoración
<br>
<select name="valoracion">
<option value=1>Repelente
<option value=2>Mal
<option value=3 selected>Regular
<option value=4>Bien
<option value=5>Fant&aacute;stica
</select>
</td>
<td ALIGN=CENTER class=fuente8 valign="middle">
Comentarios:
<br>
<textarea name="comentario" cols="30" rows="7"></textarea>
</td>
</tr>
<tr>
<td colspan=2 align=center class=fuente8>
<br>
<input type="submit" value=" Enviar la firma al libro de visitas ">
</td>
</tr>
Autor: Ing. Oscar R. Espeche
19
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

</table>
</td>
</tr>
</table>
</form>

Autor: Ing. Oscar R. Espeche


20
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-2 Sistema de encuestas


Algunas veces deseamos saber ciertas preferencias de los visitantes de nuestra pagina o qué
opiniones tienen sobre algún tema específico. Una solución a esto es tener un sistema de
encuestas, el cual contenga opciones que se puedan votar. Antes de empezar debemos tener
en cuenta que nuestro sistema de encuesta debe tener los siguientes requerimientos.

• Permitir al usuario votar ente un número de opciones predefinidas


• Permitir al usuario ver el resultado de las encuestas
• Permitir al usuario conocer el total de encuestas evaluadas al momento de la lectura de
las encuestas
• Los resultados se mostraran en forma gráfica y numeral

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.

Nota: La tabla de datos de administración no afecta directamente al funcionamiento


del sistema de encuestas. Simplemente serviría para guardar nombres de usuario y
clave de las personas que podrían administrar la aplicación de encuestas. No la
vamos a ver por ahora

Nuestra primera tabla constará de un registro por cada encuesta, de 10 campos de la


siguiente manera.

• Un campo para la pregunta de la encuesta


• Cuatro posibles respuestas, las cuales serán las que nos interesa saber
• Cuatro valores acumulativos del número de votos por cada respuesta
• Un campo para el valor total de votos

El script SQL para la creación de la tabla se encuentra a continuación.

CREATE DATABASE alumno1;


USE encuestas;
CREATE TABLE encuestas (
encid int(11) NOT NULL auto_increment,
encprg varchar(50) default NULL,
encrpt1 varchar(50) default NULL,
encrpt2 varchar(50) default NULL,
encrpt3 varchar(50) default NULL,
encrpt4 varchar(50) default NULL,
encval1 int(11) NOT NULL default '0',
Autor: Ing. Oscar R. Espeche
21
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

encval2 int(11) NOT NULL default '0',


encval3 int(11) NOT NULL default '0',
encval4 int(11) NOT NULL default '0',
enctot int(11) NOT NULL default '0',
PRIMARY KEY (encid)
) TYPE=MyISAM;

Imagenes y páginas a utilizar en el sistema de encuestas

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í

<IMG HEIGHT="5" WIDTH="100%" SRC=" barra1.gif">

Las imágenes que tendremos serán las siguientes:

barra1.gif
barra2.gif
barra3.gif
barra4.gif

Las páginas involucradas

Antes de empezar a comenzar con el código PHP de este sistema de encuestas vamos a
describir las principales páginas involucradas.

Página que muestra la encuesta

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.

Página que contabiliza el voto y muestra los resultados

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.

Autor: Ing. Oscar R. Espeche


22
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Elaboración de las páginas

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.

Página que muestra la encuesta

Ahora diseñaremos nuestro formulario de encuesta. Este formulario deberá conectarse a


nuestra base de datos para obtener la pregunta y las posibles respuestas.

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.

Imagen ejemplo de una encuesta

Para extraer la encuesta introducida se utilizará una sentencia SQL en la que se ordenarán las
encuestas por su identificador, de manera descendente.

SELECT * FROM encuestas WHERE encid = $encid

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.

Autor: Ing. Oscar R. Espeche


23
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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();}

if(!(isset($envio) && isset($voto))){// si no se recibieron datos de la consulta , mostrar el formulario


para votar

$sql = "SELECT * FROM encuestas WHERE encid = $encid ";


$resultado = @mysql_query($sql,$miconecccion);
$row = mysql_fetch_array($resultado);
?>
<P ALIGN="center">

<!-- la tabla de las preguntas con el formulario para votar -->


<table border = 0 bgcolor = "#bbbbbb">
<FORM METHOD="post" ACTION="<?= $PHP_SELF?>">
<tr><td bgcolor= "#ccaaaa" align = "rigth"><b><?=$row["encprg"]?></b></td></tr><BR><BR>
<tr><td align = "right"><?=$row["encrpt1"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="1"></td></tr><BR>
<tr><td align = right><?=$row["encrpt2"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="2"></td></tr><BR>
<tr><td align = right><?=$row["encrpt3"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="3"></td></tr><BR>
<tr><td align = right><?=$row["encrpt4"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="4"></td></tr><BR>

<!-- 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

<INPUT TYPE="Hidden" NAME="encid" VALUE='<? echo $row["encid"]?>'>


<INPUT TYPE="Hidden" NAME="envio" VALUE="envio">
<tr><td align = middle><INPUT TYPE="Submit" CLASS="boton" VALUE="Votar"></td></tr><BR>
</FORM>
</table></P>
<?}

La página, almacena en una variable llamada voto, el valor de la respuesta de nuestro


encuestado, para luego ser enviada a la página de resultados.

Página que contabiliza y muestra los resultados de la encuesta

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:

UPDATE encuestas SET encval$voto = encval$voto+1, enctot = enctot+1 where


encid=$encid

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.

Imagen ejemplo de los resultados de una encuesta

Finalmente, nuestra página mostrará el resultado de la encuesta, aquí dimensionaremos el


tamaño de las imágenes para mostrar los resultados mediante porcentajes, los cuales serán
Autor: Ing. Oscar R. Espeche
25
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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:

<IMG HEIGHT="5" WIDTH="<? echo


$SQLrow["encval1"]*100/$SQLrow["enctot"]?>%" SRC="barra1.gif">

También por simplicidad usamos un archivo .gif para todas las barras al que llamamos pic.gif.

Nuestro script quedará de la siguiente manera:

else{// si se recibieron los datos, actualizar


$sqlupdate = "UPDATE encuestas SET encval$voto = encval$voto+1, enctot = enctot+1
WHERE encid = $encid ";
if(!@mysql_query($sqlupdate,$miconecccion)){echo "Error: ".mysql_error();}// actualiza la base

$sql = "SELECT * FROM encuestas WHERE encid = $encid";


$resultados = @mysql_query($sql,$miconecccion);// consulta la base para leer los resultados
$row = mysql_fetch_array($resultados);
?>
<!-- Muestra los resultados -->
<P ALIGN="center"><font size="4"><strong><em>RESULTADOS PARCIALES DE LA
ENCUESTA:</em></strong></font></P>
<P ALIGN="center"><strong><font size="2" face="Verdana, Arial, Helvetica, sans-serif"> <? echo
$row["encprg"] ?> </font></strong></P>
<center>
<TABLE ALIGN="center" bgcolor = #cccccc>
<tr><td>
<TABLE ALIGN="center" WIDTH="400" BORDER="0" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt1"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval1"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval1"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt2"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval2"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval2"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt3"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval3"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval3"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt4"]?></TD>
<TD WIDTH="*"><IMG HEIGHT="15" WIDTH="<?=$row["encval4"]*100/$row["enctot"]?>%"
Autor: Ing. Oscar R. Espeche
26
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Autor: Ing. Oscar R. Espeche


27
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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))){

$sql = "SELECT * FROM encuestas WHERE encid = $encid ";


$resultado = @mysql_query($sql,$miconecccion);
$row = mysql_fetch_array($resultado);
?>
<P ALIGN="center">
<table border = 0 bgcolor = "#bbbbbb">
<FORM METHOD="post" ACTION="<?= $PHP_SELF?>">
<tr><td bgcolor= "#ccaaaa" align = "rigth"><b><?=$row["encprg"]?></b></td></tr><BR><BR>
<tr><td align = "right"><?=$row["encrpt1"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="1"></td></tr><BR>
<tr><td align = right><?=$row["encrpt2"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="2"></td></tr><BR>
<tr><td align = right><?=$row["encrpt3"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="3"></td></tr><BR>
<tr><td align = right><?=$row["encrpt4"]?> <INPUT TYPE="Radio" NAME="voto"
VALUE="4"></td></tr><BR>
<INPUT TYPE="Hidden" NAME="encid" VALUE='<? echo $row["encid"]?>'>
<INPUT TYPE="Hidden" NAME="envio" VALUE="envio">
<tr><td align = middle><INPUT TYPE="Submit" CLASS="boton" VALUE="Votar"></td></tr><BR>
</FORM>
</table></P>
<?}
else{
$sqlupdate = "UPDATE encuestas SET encval$voto = encval$voto+1, enctot = enctot+1
WHERE encid = $encid ";
if(!@mysql_query($sqlupdate,$miconecccion)){echo "Error: ".mysql_error();}
Autor: Ing. Oscar R. Espeche
28
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

$sql = "SELECT * FROM encuestas WHERE encid = $encid";


$resultados = @mysql_query($sql,$miconecccion);
$row = mysql_fetch_array($resultados);
?>
<P ALIGN="center"><font size="4"><strong><em>RESULTADOS PARCIALES DE LA
ENCUESTA:</em></strong></font></P>
<P ALIGN="center"><strong><font size="2" face="Verdana, Arial, Helvetica, sans-serif"> <? echo
$row["encprg"] ?> </font></strong></P>
<center>
<TABLE ALIGN="center" bgcolor = #cccccc>
<tr><td>
<TABLE ALIGN="center" WIDTH="400" BORDER="0" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt1"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval1"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval1"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt2"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval2"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval2"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt3"]?></TD>
<TD><IMG HEIGHT="15" WIDTH="<?=$row["encval3"]*100/$row["enctot"]?>%"
SRC="pic.gif"></TD>
<TD ALIGN="center" WIDTH="70"><?=$row["encval3"]?> votos</TD>
</TR>
<TR>
<TD ALIGN="center" WIDTH="100"><?=$row["encrpt4"]?></TD>
<TD WIDTH="*"><IMG HEIGHT="15" WIDTH="<?=$row["encval4"]*100/$row["enctot"]?>%"
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>";
}?>

Autor: Ing. Oscar R. Espeche


29
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-3 Contador de visitas acumuladas


En esta ocasión veremos cómo crear de manera sencilla y con un archivo de texto un contador
de visitas en PHP.

Para ello es necesario contar con 2 archivos:

contador.txt

Archivo de texto en donde iremos acumulando el número de visitas. Su valor inicial será 0
(cero).

contador.php

Página PHP encargada de aumentar de 1 en 1 el número dentro de contador.txt.

El código de la página contador.php es la siguiente (la explicación se encuentra comentada


dentro del mismo):

contador.php

<?

// Archivo en donde se acumulará el numero de visitas


$archivo = "contador.txt";

if(!file_exists($archivo)){//si no existe lo crea


@fopen($archivo, “w”);
}

// Abrimos el archivo para solamente leerlo (r de read)


$abre = @fopen($archivo, "r");

// Leemos el contenido del archivo


$total = @fread($abre, filesize($archivo));

// Cerramos la conexión al archivo


@fclose($abre);

// Abrimos nuevamente el archivo


$abre = @fopen($archivo, "w");

// Sumamos 1 nueva visita


$total = $total + 1;

Autor: Ing. Oscar R. Espeche


30
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

// Y reemplazamos por la nueva cantidad de visitas


$grabar = fwrite($abre, $total);

// Cerramos la conexión al archivo


fclose($abre);

// Imprimimos el total de visitas dándole un formato


echo "<font face='verdana' size='2'>Total de visitas:".$total."</font>";
?>

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.

Autor: Ing. Oscar R. Espeche


31
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-4 Contando visitantes activos con PHP


En este ejemplo, mostramos una forma sencilla de contabilizar los usuarios activos (que se
encuentran conectados en una sesión) de nuestro sitio, usando para ese propósito una tabla.
Dentro de dicha tabla, iremos almacenando los distintos números IP de los visitantes de
nuestro sitio y la hora y fecha en la que el visitante ha ejecutado por última vez el script.

Asimismo, la tabla ha de ir borrando progresivamente las sesiones que no hayan sido


renovadas en un tiempo que nosotros consideremos límite. Nosotros hemos fijado dicho límite
en 24 minutos que es el tiempo máximo tomado por defecto por PHP para suprimir los datos
de una sesión.

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.

Pasemos a continuación a mostrar el script que utilizaremos como librería:

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

//asignamos un nombre nemotécnico a la variable


$ip = $REMOTE_ADDR;
//definimos el momento actual
$ahora = time();

//conectamos a la base de datos


//Usad nuestros propios parametros!!
$host = 'localhost';
$user = 'alumno1';
$password = 'alumno';
$base = 'alumno1' ;
$conn = mysql_connect($host,$user,$password);
mysql_select_db($base,$conn);//tenemos que crear la base y la tabla, aparte.

//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);

//miramos si el ip del visitante existe en nuestra tabla


$ssql = 'select ip, fecha from control_ip where ip = "'.$ip.'"';

$result = mysql_query ($ssql,$conn);

//si existe actualizamos el campo fecha


if (mysql_num_rows($result) != 0) $ssql = "update control_ip set fecha = ".$ahora." where
ip = '$ip'";
//si no existe insertamos el registro correspondiente a la nueva sesión
else $ssql = "insert into control_ip (ip, fecha) values ('$ip', $ahora)";

//ejecutamos la sentencia sql


mysql_query($ssql);

//calculamos el numero de sesiones


$ssql = "select ip from control_ip";
$result = mysql_query($ssql);
$usuarios = mysql_num_rows($result);

//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;
}
?>

Podemos observar, que el script es expresado en forma de función. Después de definir la IP y


el momento en el que el script está siendo ejecutado, pasamos a interaccionar con la base de
datos. Dentro de este proceso, podemos distinguir distintas fases:

• Conexión con la base de datos


• Barrido de la tabla para eliminar los registros obsoletos.
• Inserción o actualización de un registro dependiendo de si el visitante es nuevo o no.
• Cómputo del número de registros de la tabla

La función finaliza liberando el espacio de memoria utilizado en sus consultas y enviando el


resultado del cálculo efectuado.

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.

El siguiente código usa al anterior para mostrar en pantalla la cantidad de usuarios


actualmente conectados en dicha página.

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>

La salida en el navegador será simplemente como:

Autor: Ing. Oscar R. Espeche


35
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-5 Mandar mails desde PHP

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.

Devuelve true si se envió el mensaje correctamente y false en caso contrario.

Parámetros necesarios en todos los casos

Destinatario: la dirección de correo o direcciones de correo que han de recibir el mensaje. Si


incluimos varias direcciones debemos separarlas por una coma.

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.

Ejemplo de envío de un mail sencillo

<?
mail("pepito@pepe.com,maria@yahoo.com","un asunto","Este es el cuerpo del mensaje")
?>

Parámetros opcionales del envío de correo

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.

Ejemplo complejo de envío de correo

Vamos a enviar un correo con formato HTML a pepito@pepe.com, con copia a


mariano@pepe.com y con copia oculta para pepe@pepe.com y juan@juan.com. La dirección
de respuesta la configuraremos a maria@pepe.com.

<?
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>
';

//para el envío en formato HTML


$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1\r\n";

//dirección del remitente


$headers .= "From: Pepito Pepe <pepito@pepe.com>\r\n";

//dirección de respuesta, si queremos que sea distinta que la del remitente


$headers .= "Reply-To: mariano@pepe.com\r\n";

//direcciones que recibián copia


$headers .= "Cc: maria@pepe.com\r\n";

//direcciones que recibirán copia oculta


$headers .= "Bcc: pepe@pepe.com,juan@juan.com\r\n";

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.

Si nuestro web está en un servidor de un proveedor de hosting seguramente deberá estar


configurado PHP para el envío de mails. Si estamos trabajando en un servidor propio, sí
tendremos que configurar nuestro PHP.

Autor: Ing. Oscar R. Espeche


37
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

En sistemas Windows encontraremos php.ini en el directorio windows o dentro de este, en el


subdirectorio system32 o similar. En este sistema deberemos indicar el dominio del servidor de
smtp, algo como smtp.midominio.com. Si es el computador local el que hace de servidor,
podremos poner "localhost" como máquina que enviará el correo. También podemos
especificar la dirección desde donde queremos que parezca que se envía el mensaje en caso
de que no se indique otra durante el envío.

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

<td><input type="text" name="asunto" size="30"> </td>


</tr>
<tr>
<td><b>Mensaje:</b></td>
<td><textarea name="mensaje" cols="45" rows="7"></textarea><p></td>
</tr>

<tr>
<td><input type="submit" value="Enviar!"></td>
<td></td>
</tr>
</table>
</center>

</form>
</body>
</html>

El archivo para enviar el mail seria como:

enviar.php

<?
if($destino!=""){

//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 recibián copia


$headers .= "Cc: “.$ccc.”\r\n”;

//direcciones que recibirán copia oculta


$headers .= "Bcc: “.$bcc.”\r\n”;

mail($destino, $asunto, $mensaje, headers);


echo "Se ha enviado el mensaje a $destino correctamente!";
}
else{
echo "Debes escribir un destinatario válido para enviar el email";
}
?>

Y listo! Ya sabes cómo enviar correos a través de PHP.

Autor: Ing. Oscar R. Espeche


39
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Validar una dirección de email

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.

Código de la función: archivo comprobar.php

<?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.

En el segundo if comprueba que no tiene algunos caracteres no permitidos. Y los restantes


hacen comprobaciones de las distintas partes de la dirección de correo, a saber: Que hay un
punto en algún lado y que la terminación del dominio es correcta y que el principio de la
dirección también es correcto.

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";
}
?>

Autor: Ing. Oscar R. Espeche


42
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-6 Contactar con el visitante


Bien sabido es que una de las tareas más importantes y laboriosas del ciclo de vida de una
página web es su mantenimiento, para conservar la web, su tráfico y su importancia con el
tiempo. Pero mantener una web no es sólo publicar nuevos contenidos y actualizar los
anteriores, entre estas tareas se encuentra una que es fundamental: proporcionar mecanismos
para que los visitantes se puedan poner en contacto contigo, y, por supuesto, contestar a cada
uno de los mensajes que recibes.

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.

Correo electrónico desde nuestro cliente de e-mail

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:

Se ha de poner un enlace convencional, pero su atributo HREF va dirigido a una dirección de


correo con la palabra mailto:.

<A HREF="mailto:pepe@pepe.com">Escríbeme</A>

Quedaría así: Escríbeme. Haciendo clic en el enlace podrás comprobar su funcionamiento.

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

Podemos utilizar un formulario para comunicarnos. En el formulario nuestro visitante puede


introducir sus datos y la consulta o sugerencia que desea realizar, pulsando luego un botón,
para enviar por correo electrónico a la persona de contacto todos los datos.

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:

• Ayudar al visitante a componer el mensaje, y así incentivar su comunicación.


• Forzar a que el visitante introduzca cierta información que te pueda resultar importante.

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

Un boletín de novedades o newsletter es un correo electrónico que se envía periódicamente a


los visitantes de nuestro sitio que han deseado apuntarse. En dicho correo se suelen señalar
las novedades ocurridas en nuestro sitio, ya se trate de nuevos contenidos o servicios. La
periodicidad del boletín puede ser variable en función de las necesidades de nuestro web,
aunque se recomienda que sea siempre la misma.

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.

Autor: Ing. Oscar R. Espeche


44
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Por qué debemos hacer un boletín

La primera razón de crear un boletín es fomentar la fidelidad de nuestros visitantes. Los


boletines tienen un grado alto de respuesta por parte de los destinatarios, lo que hace que
cada vez que lo envíes obtengas una buena cantidad de visitas.

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.

Cuando creamos y mantenemos un boletín de novedades, damos una imagen de estar


actualizando la página constantemente. Cada vez que un usuario lo recibe sabe que
hemos introducido novedades y los visitantes que encuentran en nuestra página la opción de
apuntarse pueden deducir que actualizamos la página constantemente, aunque no lleguen a
plantearse el suscribirse.

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.

Posibilidades para el envío de corrreo masivo

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.

Nota: no es normal enviar el boletín con nuestro programa de correo, dirigiendo el


mensaje a múltiples usuarios. Sin embargo, si el número de usuarios es reducido
Autor: Ing. Oscar R. Espeche
45
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Como escribir newsletters

Resumen:

1. Las conclusiones al principio.


2. Lo bueno si breve 2 veces bueno.
3. Procura no abusar del HTML dentro del mail.
4. Como mínimo una vez al mes. Como máximo una vez a la semana.
5. Un breve consejo cuando enviemos mensaje a muchos amigos

1. Las conclusiones al principio:

Como siempre. Procura decir lo interesante en el primer párrafo. Deja lo demás para el final.

Ahora veamos las partes de un mail:

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.

2. Lo bueno, si es breve, 2 veces bueno.

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.

3. No abuses del HTML

Cuando esta bien usar el html en el mail:

• Para incluir enlaces largos que pueden cortarse en el correo.


• Para incluir fuentes, color y tablas que ayuden a leer el correo.

Cuando no está bien incluir html en el mail:

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.

Autor: Ing. Oscar R. Espeche


48
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

5. Un breve consejo cuando enviemos mensaje a muchos amigos

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.

Creación de boletines en formato HTML

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.

1) Mandar las imágenes como archivos adjuntos

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.

2) Mandar el mensaje sin imágenes adjuntas

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

Autor: Ing. Oscar R. Espeche


49
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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:

<a href="http://www.pepe.com/manuales">Manuales de Pepe.com</a>

<img src="http://www.pepe.com/images/logo.gif" width=120 height=70>

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">

Enviando correo en formato HTML, a la lista

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.

Nuestro boletín puede tener un código como el siguiente:

<html>
<head><link rel="STYLESHEET" type="text/css" href="http://www.pepe.com/estilo.css">
<base target="_blank">
</head>

Autor: Ing. Oscar R. Espeche


50
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

<body bgcolor="ffffff" topmargin=0 leftmargin=0 marginheight=0 marginwidth=0>


<table width="100%" cellspacing="0" cellpadding="0" border="0" bgcolor="000033"
background="http://www.pepe.com/images/fondoarriba.gif">
<tr>
<td align="center" background="http://www.pepe.com/images/plantilla/trama3.gif"> <b><font
face="verdana,arial,helvetica" size="4" color=ffffff>Boletín de novedades de Pepe.com</font></b></td>
</tr>
<tr>
<td bgcolor="bbbb55" align="center"><span class=fuente8><font face="verdana,arial,helvetica"
size="1">
Número#13 1 de febrero de 2004</font></span>
</table>
<table width="100%" cellspacing="0" cellpadding="0" border="0" bgcolor="cccc66">
<tr>
<td bgcolor="bbbb55" align="center">
<a href="http://www.pepe.com/desarrolladores" target="_blank">
<img src="http://www.pepe.com/images/banners/d_desarrolladores.gif" width="468" height="60"
border="0" alt="Pincha para acceder al directorio de desarrolladores" vspace="3"></a>
<br>
</td>
</tr>
</table>
<br>
<table width="100%" cellspacing="0" cellpadding="2" border="0">
<tr>
<td valign="top">
<font face="verdana,arial,helvetica" size="2">
Tenemos un montón de artículos nuevos que seguro que les interesarán.
<br>
<br>
<b>CONTENIDOS</b>
<br>
1.- Nuevos artículos
<br>
2.- Nuevos programas
<br>
<br>
.....
<br>
<br>
<b><a href="http://www.pepe.com/manuales/24/">Calendario PHP</a></b>
<br>
Aplicación práctica de PHP en la que construimos un calendario que muestra el mes y año actual y permite
moverse a otro mes y año.
</td></tr></table>
</body>
</html>

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.

Newsletters que sirven para vender

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

• Procura que en el tema sea corto y honesto.


• Titulares en capitales generan mas acción (evita todo mayúsculas o minúsculas).
• Procura generar curiosidad y confianza.

"Tema" Recomendado "Tema" No recomendado

Hipotecas Consigue tu Hipoteca.

Nuevo Computador CONSIGUE TU PC GRATIS AHORA!!!

Comparativa De Bancos seguro que tu banco es el mejor?

Vaqueros Rebajados 50% AHORA es el momento de comprar Vaqueros!!!

Es crucial el no "chillar" al usuario con un mensaje agresivo.

2. El "quien" debe ofrecer información honesta y utilizar una direccion de correo a


la que se pueda responder.

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.

3. Ofrece información clara y útil. Debes generar Acción.

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.

Resume, resume y resume

Autor: Ing. Oscar R. Espeche


53
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

5. Prueba el mail en grupos reducidos para corregir.

Dentro de tu empresa, entre amigos, usuarios seleccionados, un parte de tu lista de correo,


cualquier muestra será buena para comprobar que "alias", "tema" y contenido de la newsletter
es mejor.

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).

6. Lanza diferentes versiones para testear resultados.

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

Autor: Ing. Oscar R. Espeche


54
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Autor: Ing. Oscar R. Espeche


55
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-7 Programando con sockets en PHP


El término ”sockets”se le atribuye a una forma de conexión que realiza un programa de la
capa de aplicación con la capa de transporte.

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”.

La diferencia entre cliente y servidor es fundamentalmente a que un servidor debe abrir un


“sockets” de una manera especial para esperar en él una petición de un cliente. Normalmente
se especifica la dirección Ip y el número de puerto que caracterizan a todo “sockets”. El puerto
definido por el servidor es un puerto “bien conocido” a donde recurrirá el cliente.

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");

// conecta el socket con el puerto


$result = socket_bind($socket, $host, $port) or die("Error al conectar el puerto\n");

// espera a los clientes en el puerto


$result = socket_listen($socket, 3) or die("Error al crear la espera\n");

// acepta conexiones entrantes


// abre otro socket para manejar la conexión
$spawn = socket_accept($socket) or die("No se pueden aceptar conexiones\n");

// lee la solicitud del cliente


$input = socket_read($spawn, 1024) or die("Could not read input\n");

// elimina caracteres impuros de la entrada


$input = trim($input);

// invierte la cadena
$output = strrev($input) . "\n";

// devuelve la cadena invertida


socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n");

// cierra los sockets


socket_close($spawn);
socket_close($socket);

Autor: Ing. Oscar R. Espeche


57
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

?>

Veamos una explicación más detallada:

Se define la dirección Ip y el puerto con un máximo de 65535.

<?
$host = "172.16.10.178";
$port = 1234;
?>

Se define el timeout de la conexión con el cliente.

<?
set_time_limit(0);
?>

Se crea el socket para obtener el manipulador que nos habilita a realizar


operaciones con el socket.

<?
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("..........");
?>

El parámetro AF_INET especigica el dominio (Internet), mientras que SOCK_STREAM indica


tipo de socket TCP.

Si fuese tipo UDP sería:

<?
$socket = socket_create(AF_INET, SOCK_DGRAM, 0) or die("............");
?>

Luego viene la conexión con el puerto.

<?
$result = socket_bind($socket, $host, $port) or die("...............");
?>

Autor: Ing. Oscar R. Espeche


58
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

El servidor espera al cliente en el puerto indicado y define el número de buffers de entrada


( en este caso, 3).

<?
$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("..............");
?>

Con la conexión establecida el server lee la petición del cliente.

<?
$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.

El servidor procesa la petición. En este caso simplemente invierte la cadena y la devuelve


al cliente.

<?
$output = strrev($input) . "\n";
socket_write($spawn, $output, strlen ($output)) or die("........");
?>

La función socket_write() tiene tres parámetros: la referencia al socket, el contenido de la


salida, y el número de bytes a transmitir.
Autor: Ing. Oscar R. Espeche
59
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Finalmente cierra los sockets.

<?
socket_close($spawn);
socket_close($socket);
?>

Conectar con el servidor

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.

La ejecución de nuestro programa sería :

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:

$ telnet 172.16.10 1234


Trying 192.168.1.202...
Connected to administrador.adminnet.edu.ar
Escape character is '^]'.

Hola como te va

av et omoc aloH

Connection closed by foreign host.

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");

// conecta el socket con el puerto


$result = socket_bind($socket, $host, $port) or die("Error al conectar el puerto\n");

// espera a los clientes en el puerto


$result = socket_listen($socket, 3) or die("Error al crear la espera\n");

// acepta conexiones entrantes


// abre otro socket para manejar la conexión
$spawn = socket_accept($socket) or die("No se pueden aceptar conexiones\n");

$saludo="Bienvenido, el servidor esta esperando \n\r\n\r";


socket_write($spawn,$saludo , strlen ($saludo)) or die("Error de escritura\n");

// lee la solicitud del cliente


//si el caracter es "#" corta la conexión
while(($input = socket_read($spawn,1024)) != "#") {
$i.= $input;
//si el caracter es "@" termina la recepción del string
while(($input = socket_read($spawn,1024)) != "@") {
$i.= $input;
}
// elimina caracteres impuros de la entrada
$input = trim($i);

// 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

Autor: Ing. Oscar R. Espeche


61
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Hasta ahora nos conectamos con el cliente Telnet. Sin embargo es muy fácil escribir nuestro
propio cliente PHP.

Veremos como podemos enviar datos adquiridos mediante un formulario al servidor de


nuestro ejemplo.

Cliente.php

<html>
<head>
</head>
<body>
<?
if (!$submit)
{
?>

<form action="<? echo $PHP_SELF; ?>" method="post">


Introduzca algún texto:<br>
<input type="Text" name="mensaje" size="15">
<input type="submit" name="submit" value="Enviar">
</form>

<?
}
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);

// enviar la cadena al servidor


fputs ($fp, $mensaje);

// tomar la contestación
$result = fgets ($fp, 1024);

// cerrar la conexión
fputs ($fp, "END");

Autor: Ing. Oscar R. Espeche


62
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

fclose ($fp);

// limpiar la respuesta
$result = trim($result);

// enviar la contestación al browser


}
?>
Contestación del servidor: <b><? echo $result; ?></b>
<?
}
?>
</body>
</html>

Un programa alternativo podría ser el siguiente:

Cliente2.php

<html>
<head>
</head>
<body>
<?
if (!$submit)
{
?>

<form action="<? echo $PHP_SELF; ?>" method="post">


Introduzca algún texto:<br>
<input type="Text" name="mensaje" size="15">
<input type="submit" name="submit" value="Enviar">
</form>

<?
}
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.

Conexión con un servidor POP3


Veamos como se conecta un cliente POP3 con el servidor mediante sockets para obtener los
mensajes del mailbox.

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.

$ telnet mail.host 110


Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
+OK POP3 mail.host v5.5 server ready

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.

El servidor nos indica que tenemos 72 mensajes en nuestro mailbox.

Para hacer lo mismo con PHP:

<?
$host="192.168.0.202";
$port = 110;
$user = "juan";
$pass = "clave";

Autor: Ing. Oscar R. Espeche


64
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

$fp = fsockopen ($host, $port, $errno, $errstr);

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);

// enviar password y tomar respuesta


fputs ($fp, "PASS $pass\n");
$ack = 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

// obtener el contenido de STATUS


$arr = explode(" ", $status);

// el segundo elemento contiene el número de mensajes


echo $arr[1] . " mensajes en mailbox";
}
?>

Login en un servidor Unix

Veremos un programa que usa sockets para enviar nombre y password a un


servidor Unix.

<?

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);

// Se autentica usuario:pasword contra el archivo /etc/passwd


// retorno: -1 si el usuario no existe
// 0 si la clave es incorrecta
// 1 si nombre y clave son correctos

function authenticate($user, $pass)


{
$result = -1;
// se debe tener permisos para leer este archivo
$data = file("/etc/passwd");

foreach ($data as $line)


{
$arr = explode(":", $line);

if ($arr[0] == $user)
{
Autor: Ing. Oscar R. Espeche
66
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

// se obtiene los dos caracteres del salt


$salt = substr($arr[1], 0, 2);

if ($arr[1] == crypt($pass, $salt))


{
$result = 1;
break;
}
else
{
$result = 0;
break;
}
}
}

return $result;
}
?>

Veamos el resultado de la conexión al servidor con Telnet:

$ telnet 192.168.1.202 1234


Trying 192.168.1.202...
Connected to 192.168.1.202.
Escape character is '^]'.

juan:clave
1Connection closed by foreign host
......................................................

$ telnet 192.168.1.202 1234


Trying 192.168.1.202...
Connected to 192.168.1.202.
Escape character is '^]'.
cualquiernombre:hahaha
-1Connection closed by foreign host

Network News Transfer Protocol

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

usando los diferentes comandos disponibles para tal efecto.

¿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);
}

?>

Hablando con el Servidor

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.

Autor: Ing. Oscar R. Espeche


68
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Ejemplo:

telnet my.news.host 119

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 .

Tras recibir el comando "GROUP es.comp.os.linux.programacion", el servidor de News contesta


"211 232 222996 223235 es.comp.os.linux.programacion". 211 es un código definido en el
RFC (dice básicamente que el comando se ha ejecutado sin problemas - en el RFC hay más
detalles). También ha contestado que hay 232 artículos, indexados desde el 222996 hasta el
223235. Estos números se hacen llamar número de artículo. Cada artículo tiene uno único. Si
contamos: 222996 + 232 no da 232235. Los siete que faltan se borrarían del servidor de
alguna forma. Es posible que se hayan cancelado por el propio autor (sí, esto se puede hacer!)
o bien se han borrado tras una denuncia de abuso, por ejemplo.

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";

// identificación requerida en el servidor privado


if($cfgUser) {
fputs($usenet_handle, "AUTHINFO USER ".$cfgUser."\n");
$tmp = fgets($usenet_handle, 1024);

fputs($usenet_handle, "AUTHINFO PASS ".$cfgPasswd."\n");


$tmp = fgets($usenet_handle, 1024);

// check error

Autor: Ing. Oscar R. Espeche


69
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

if($tmp != "281 Ok\r\n") {


echo "502 Error de autenticación!!\n";
exit();
}
}

// seleccionar el newsgroup

fputs($usenet_handle, "GROUP ".$cfgNewsGroup."\n");


$tmp = fgets($usenet_handle, 1024);

if($tmp == "480 Authentication required for command\r\n") {


echo "$tmp\n";
exit();
}

$info = split(" ", $tmp);


$first = $info[2];
$last = $info[3];

print "First : $first\n";


print "Last : $last\n";

?>

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;

// bajando los últimos 10 artículos

$bucle=$last-$cfgLimit;

while ($bucle <= $last) {

set_time_limit(0);

Autor: Ing. Oscar R. Espeche


70
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

fputs($usenet_handle, "ARTICLE $boucle\n");

$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);

?>

Autor: Ing. Oscar R. Espeche


71
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-8 Sistema de autentificación PHP para acceso a datos restringidos

Un sistema de autentificación es un módulo de seguridad para verificar que el usuario que


visita las páginas es quien dice ser. Por supuesto, sabiendo que ese usuario es conocido,
podremos darle acceso a más aspectos de la página que si fuese un usuario desconocido.

Esquema de un sistema de autentificación

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.

Los datos de autentificación (usuario y contraseña escritos en la página inicial) se envían a la


página dibujada con línea de puntos, que se encarga de hacer una comprobación de dichos
datos del usuario. Según los datos de autentificación, se redirecciona al navegador a la página
de la aplicación restringida, en caso de que sean correctos, o a la página donde volver a
escribir el usuario/contraseña, en caso de que sean incorrectos.

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.

La aplicación de acceso restringido, aparte de mostrar las funcionalidades que queríamos


Autor: Ing. Oscar R. Espeche
72
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

¿Por qué hacemos esta comprobación de seguridad dentro de la aplicación?

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.

En caso de desear burlar la seguridad, ¿Cómo podría un usuario entrar a la página de la


aplicación si no hay enlaces directos y para pasar a ella necesitamos que nos redireccione la
página de comprobación del usuario/contraseña?

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)

Autor: Ing. Oscar R. Espeche


74
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Página inicial con el formulario de autentificación en PHP

Vamos a realizar la página inicial, que tiene el formulario de autentificación en el que el


visitante debería rellenar con su usuario y contraseña. Como es la página inicial, la llamaremos
index.php, que es el documento por defecto configurado en nuestro servidor.

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.

Para pasar a la página inicial el mensaje de que el usuario/contraseña introducidos no son


válidos utilizaremos una variable pasada a través de la URL. La llamaremos errorusuario, y si
contiene la cadena "si" es que estamos recibiendo un error.

El código sería el siguiente:


<html>
<head>
<title>Autentificación PHP</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>
<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>
</body>
</html>
Autor: Ing. Oscar R. Espeche
75
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Control de los datos de autentificación en PHP

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.

Después de la comprobación podrán pasar dos cosas:

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.

Si el usuario/contraseña no era correcto, se envía al navegador a la página de inicio pasando


la variable errorusuario=si, que indica que ha habido un error en la autentificación.

El código se puede ver a continuación:

<?
//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";

Autor: Ing. Oscar R. Espeche


76
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

header ("Location: aplicacion.php");


}else {
//si no existe le mando otra vez a la portada
header("Location: index.php?errorusuario=si");
}
?>

Capa de seguridad en PHP

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.

El módulo de seguridad, incluido al principio de cada archivo, realizará las comprobaciones


oportunas y actuará permitiendo ver el archivo o denegando su visualización dependiendo de
dichas comprobaciones.

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 no se había autentificado, redirijo al navegador a la página que tiene el formulario de


autentificación. Además, salgo del script PHP, con lo que la página deja de ejecutarse y el
resto no se verá. Sólo se mandará al navegador la redirección con lo que el navegador se
moverá al formulario y será imposible ver nada en la página segura.

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.

El código se puede ver a continuación:

<?
//Inicio la sesión
session_start();

//COMPRUEBA QUE EL USUARIO ESTA AUTENTIFICADO


if ($_SESSION["autentificado"] != "SI") {
Autor: Ing. Oscar R. Espeche
77
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

//si no existe, envío a la página de autentificación


header("Location: index.php");
//además salgo de este script
exit();
}
?>

Archivos de la aplicación con acceso restringido en PHP

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.

El código de una página segura sería el siguiente:

<?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.

Salir de la aplicación segura en PHP

La seguridad de la aplicación se basa en la definición de unas variables de sesión que se


consultan en cada página segura. Puede ocurrir que el usuario entre en la aplicación e inicie
Autor: Ing. Oscar R. Espeche
78
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Parece interesante, pues, ofrecer al visitante la opción de acabar la sesión en cualquier


momento, para asegurarnos en ese caso que la sesión se ha terminado y no se podrá acceder
si no es introduciendo nuevamente el usuario y contraseña correctos.

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>

Código realmente usado

Se muestra el código que se usó para realizar las operaciones que se indicaron en el diagrama
de flujo.

Pagina.php

<h1><b>Esta es una página no protegida con link a otra página protegida</b></h1>


<p>
bla..bla...

<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>

<a href="index1.php">Ir a la aplicación protegida</a>

<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>

Autor: Ing. Oscar R. Espeche


80
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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";

header ("Location: aplicacion.php");


}else {
//si no existe le mando otra vez a la portada
header("Location: index1.php?errorusuario=si");
}
?>

Seguridad.php

<?
//Inicio la sesión
session_start();

//COMPRUEBA QUE EL USUARIO ESTA AUTENTIFICADO


if ($_SESSION["autentificado"] != "SI") {
//si no existe, envío a la página de autentificación
header("Location: index1.php");
Autor: Ing. Oscar R. Espeche
82
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

//además salgo de este script


exit();
}
?>

Autentificación PHP para múltiples usuarios usando MySQL

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 funcionamiento del script

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.

//conecto con la base de datos


$conn = mysql_connect("$servidor","$usuario_admin","$password_admin");
//selecciono la BBDD
mysql_select_db("nombre_bbdd",$conn);

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.

//Sentencia SQL para buscar un usuario con esos datos


$ssql = "SELECT * FROM usuario WHERE nombre='$usuario' and clave='$contrasena'";

//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

<?

//conecto con la base de datos


$conn = mysql_connect("localhost","alumno1","alumno");
//selecciono la BBDD
mysql_select_db("alumno1",$conn);

$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);

//vemos si el usuario y contraseña es váildo


//si la ejecución de la sentencia SQL nos da algún resultado
//es que si que existe esa conbinación usuario/contraseña

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);
?>

Autor: Ing. Oscar R. Espeche


85
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

Autor: Ing. Oscar R. Espeche


86
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-9 Calendario con PHP


Vamos a construir una página en PHP con un calendario, donde inicialmente se muestra el
mes y año actual y por el que podremos navegar, a través de un formulario y enlaces, para
mostrar otro mes y año cualquiera.

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.

Resumen del ejercicio

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.

Archivo índice del calendario PHP


Hemos hecho un archivo índice lo más pequeño posible, con nombre index.php. Como
decíamos, la complejidad de este ejercicio nos la guardamos para la librería calendario que es
donde están las funciones realmente portables. Este archivo, por tanto, no interesa mucho a la
hora de trasladar este calendario a otras aplicaciones, pero echarle un vistazo nos preparará
para saber las funciones que debemos utilizar de la librería.

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");

if (!$HTTP_POST_VARS && !$HTTP_GET_VARS){


$tiempo_actual = time();
$dia = date("j", $tiempo_actual);
$mes = date("n", $tiempo_actual);
$ano = date("Y", $tiempo_actual);
}else {
$dia = 1;
$mes = $nuevo_mes;
$ano = $nuevo_ano;
}

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.

Luego, ya en el cuerpo de la página, tenemos el código PHP que se encarga de hacer el


cálculo de la fecha a mostrar y muestra el calendario y el formulario.

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

Además, hacemos una llamada a la función formularioCalendario(), también pasándole los


valores del mes y año, para que presente en pantalla el formulario que nos permitirá pasar de
una fecha a otra.

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)

Es la función más importante de nuestra librería. Se encarga de dibujar en pantalla el


calendario con todos sus días. El calendario lo haremos en una tabla de HTML, así que iremos
escribiendo el calendario desde la parte superior, utilizando las correspondientes etiquetas
HTML.

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.

//tomo el nombre del mes que hay que imprimir


$nombre_mes = dame_nombre_mes($mes); //convierte el número en el nombre del mes

//construyo la tabla que incluye al gráfico del mes


echo "<table width=200 cellspacing=3 cellpadding=2 border=0><tr><td colspan=7
Autor: Ing. Oscar R. Espeche
89
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

align=center class=tit>";

//construyo la tabla que incluye al encabezado << mes año >>

echo "<table width=100% cellspacing=2 cellpadding=2 border=0><tr><td style=font-


size:10pt;font-weight:bold;color:white>";

//calculo el mes y año del mes anterior


$mes_anterior = $mes - 1; //los meses van de 1 al 12
$ano_anterior = $ano;
if ($mes_anterior==0){ //es diciembre del año anterior
$ano_anterior--;
$mes_anterior=12;
}

//dibujo las flechitas <<


echo "<a style=color:white;text-decoration:none
href=index.php?nuevo_mes=$mes_anterior&nuevo_ano=$ano_anterior> &lt;&lt;
</a></td>";

//escribo mes año


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;
}

//dibujo las flechitas >>


echo "<a style=color:white;text-decoration:none
href=index.php?nuevo_mes=$mes_siguiente&nuevo_ano=$ano_siguiente> &gt;&gt;
</a></td></tr></table></td></tr>"; //termina la tabla que contiene al encabezado y la fila
que la contiene.

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.

Luego tenemos el siguiente código:

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>';

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.

Autor: Ing. Oscar R. Espeche


91
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

//Variable para llevar la cuenta del dia actual


$dia_actual = 1;

//calculo el numero del dia de la semana del primer dia


$numero_dia = calcula_numero_dia_semana(1,$mes,$ano);

//calculo el último dia del mes


$ultimo_dia = ultimoDia($mes,$ano);

Acabamos de utilizar dos nuevas funciones:

• 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.

Estas funciones serán explicadas más adelante

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.

//escribo la primera fila de la semana


echo "<tr>";
for ($i=0;$i<7;$i++){
if ($i < $numero_dia){
//si el dia de la semana i es menor que el numero del primer dia de la semana
//no pongo nada en la celda
echo "<td></td>";
} else {
//pongo el número de día del mes en la celda
echo "<td align=center>$dia_actual</td>";
$dia_actual++;
}
}
echo "</tr>";

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.

//recorro todos los demás días hasta el final del mes


$numero_dia = 0;
while ($dia_actual <= $ultimo_dia){
//si estamos a principio de la semana escribo el <TR>
if ($numero_dia == 0)
echo "<tr>";

echo "<td align=center>$dia_actual</td>";


$dia_actual++; //actualizo el número del dia del mes
$numero_dia++; //actualizo el contador de los días de la semana
//si es el ultimo de la semana, pongo al principio de la semana y escribo el </tr>
if ($numero_dia == 7){ //empezamos de 0
$numero_dia = 0;
echo "</tr>";
}
}

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.

Si estamos al principio de la semana ($numero_dia = 0) entonces escribo el inicio de fila con


<tr>; Si estamos al final de la fila ($numero_dia = 7) entonces pongo el final de la fila con
</tr>.

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).

Las últimas líneas de código de la función las vemos ahora.

//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
}

echo "</tr>"; //cierro la última semana

Autor: Ing. Oscar R. Espeche


93
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

echo "</table>"; //termina la tabla que contiene al gráfico

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.

Mostrar formulario del calendario

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.

Función formularioCalendario ($mes,$ano)

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"';

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";

Autor: Ing. Oscar R. Espeche


94
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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 <option value="12" ';

if ($mes==12) echo "selected";

echo '>Diciembre </select> </td>';

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>.

Autor: Ing. Oscar R. Espeche


95
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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>';

Autor: Ing. Oscar R. Espeche


96
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Para acabar mostramos el botón de submit del formulario y las etiquetas de cierre de tabla y
formulario.

Otras funciones de la librería del calendario

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.

Autor: Ing. Oscar R. Espeche


97
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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";

Autor: Ing. Oscar R. Espeche


98
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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.

A continuación se muestran los scripts del calendario.

index.php

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

<html>

Autor: Ing. Oscar R. Espeche


99
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

<head>

<title>Calendario PHP</title>

<link rel="STYLESHEET" type="text/css" href="estilo.css">

</head>

<body>

<div align="center">

<?

require ("calendario.php");

if (!$HTTP_POST_VARS && !$HTTP_GET_VARS){

$tiempo_actual = time();

$mes = date("n", $tiempo_actual);

$ano = date("Y", $tiempo_actual);

}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);

//construyo la cabecera de la tabla


echo "<table width=200 cellspacing=3 cellpadding=2 border=0><tr><td colspan=7 align=center class=tit>";
echo "<table width=100% cellspacing=2 cellpadding=2 border=0><tr><td style=font-size:10pt;font-
weight:bold;color:white>";
//calculo el mes y ano del mes anterior
$mes_anterior = $mes - 1;
Autor: Ing. Oscar R. Espeche
101
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

$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>&lt;&lt;</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>&gt;&gt;</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>';

//Variable para llevar la cuenta del dia actual


$dia_actual = 1;

//calculo el numero del dia de la semana del primer dia


$numero_dia = calcula_numero_dia_semana(1,$mes,$ano);
//echo "Numero del dia de demana del primer: $numero_dia <br>";

//calculo el último dia del mes


$ultimo_dia = ultimoDia($mes,$ano);

//escribo la primera fila de la semana


echo "<tr>";
for ($i=0;$i<7;$i++){
if ($i < $numero_dia){
//si el dia de la semana i es menor que el numero del primer dia de la semana no pongo nada
en la celda
echo "<td></td>";
} else {
echo "<td align=center>$dia_actual</td>";
$dia_actual++;
}
}
echo "</tr>";

//recorro todos los demás días hasta el final del mes


$numero_dia = 0;
while ($dia_actual <= $ultimo_dia){
//si estamos a principio de la semana escribo el <TR>
if ($numero_dia == 0)
echo "<tr>";
echo "<td align=center>$dia_actual</td>";
$dia_actual++;
$numero_dia++;
//si es el uñtimo de la semana, me pongo al principio de la semana y escribo el </tr>
if ($numero_dia == 7){
$numero_dia = 0;
Autor: Ing. Oscar R. Espeche
102
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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

<option value="12" ';


if ($mes==12)
echo "selected";
echo '>Diciembre
</select>
</td>';
echo '
<td align="center" valign="top">
A&ntilde;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>';
echo '
</tr>
<tr>
<td colspan="2" align="center"><input type="Submit" value="[ IR A ESE MES ]"></td>
</tr>
</table><br>

<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;
}

Autor: Ing. Oscar R. Espeche


105
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

4-10 Abstracción de datos con ADODB


Como sabemos, PHP está especialmente diseñado para la creación de sitios webs dinámicos.
Para crear estos sitios normalmente se utiliza algún tipo de base de datos desde donde
obtenemos la información que queremos mostrar, ya sean noticias, preguntas y respuestas
de un foro u otro tipo de información dinámica. Si usamos php normalmente usaremos
MySQL como base de datos para iniciar nuestro sitio, el problema aparece cuando nuestro
proyecto crece tanto que necesita hacer uso de otro tipo de base de datos más robusta.

Desafortunadamente el acceso en PHP cada base de datos es muy diferente. Para


conectarnos a mysql, debemos usar mysql_connect(); cuando decida cambiar a Oracle o
Microsoft SQL Server, debe usar ocilogon() o mssql_connect() respectivamente. Lo peor es
que también los parámetros de cada función son diferentes.

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.

En la siguiente figura se muestra en la parte superior cual es la realidad cuando se manejan


varias base de datos desde una determinada plataforma como PHP.

En el dibujo inferior se muetra como se puede transparentar las particularidades de cada


base de datos mediante el mecanismo de abstracción como lo realiza ADODB.

Autor: Ing. Oscar R. Espeche


106
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

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

Autor: Ing. Oscar R. Espeche


107
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

<?

$db = mysql_connect("localhost", "alumno1", "alumno");

mysql_select_db("alumno1",$db);

$result = mysql_query("SELECT * FROM tabla1",$db);

if ($result == false) die("falló el acceso");

while ($fields = mysql_fetch_row($result)) {

for ($i=0, $max=sizeof($fields); $i < $max; $i++) {

print $fields[$i].' ';

print "<br>";

?>

El código es bastante simple para explicarlo.

Código equivalente en ADODB

Ahora portarlo a Oracle es tan simple como cambiar la segunda línea a


NewADOConnection('oracle'). Vamos a repasar cada parte del código.

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>";
}

Conectando a la base de datos

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

$result = $db->Execute("SELECT * FROM empleados");


if ($result === false) die("falló la conexión");

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.

Existen dos objetos principales en ADODB. El objeto connection y el objeto recordset.


Una vez creados como ya vimos, podemos usar las funciones y propiedades de dichos
objetos. Cuando usar cada uno?

El objeto connection ($db) es responsable de la conexión a la base de datos, formateo de las


SQL y las consultas al servidor. El objeto recordset ($result) es responsable de la obtención
de los resultados obtenidos y el formateo de los resultados obtenidos. Los nombres “db” y
“result” pueden cambiar según se definan.

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

print $result->fields[$i].' ';


$result->MoveNext();
print "<br>";
}

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).

El array $result->fields[] es generado por ADODB ante cada petición de movenext().

Podemos obtener array asociativos, o indexados por el número del campo.

Array indexado por el número:

$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');

Para comprobar la diferencia de los arrays, podemos ejecutar la función print_r():

print_r($rs1->fields); // muestra array([0]=>'v0',[1] =>'v1', etc)


print_r($rs2->fields); // muestra array(['col1']=>'v0',['col2'] =>'v1' , etc)

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.

Autor: Ing. Oscar R. Espeche


110
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Otras funciónes especiales

$recordset->Move($pos) mueve el recordset a una fila en particular. ADODB soporta avance


de filas en todas las bases de datos. Algunas bases de datos no soportan retroceso en el
recordset. Puede de todas maneras simular este comportamiento usando un caché.

$recordset->RecordCount() retorna el total de filas obtenidas en el recordset. Algunas bases


de datos no soportan esto y se devuelven un -1.

$recordset->GetArray() coloca el resultado del recordset en un array.

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 */

Más funciónes útiles pueden ser encontradas en el manual de ADODB.

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’

Cuando cambie de base de dato este formato de datos puede no funcionar.

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.

Entonces como usamos estas funciones?

Autor: Ing. Oscar R. Espeche


111
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

$sql = "INSERT INTO tabla (id, fecha, nota) values ("


. $ID . ','
. $db->DBDate($Fecha) .','
. $db->qstr($Nota).")";
$db->Execute($sql);

ADODB tiene también dos funciones que ayudan a reconocer si un insert update o delete
han sido correctos.

$connection->Affected_Rows() (devuelve el total de filas afectadas por un insert o un delete


) y $recordset->Insert_ID() (devuelve el último valor generado por un campo autoincrement
en un insert). No todas las bases de datos soportan estas funciones (vea la documentación).

MetaTypes

Existen funciones para recuperar información de cada campo, el método


FetchField($fieldoffset). Esto devuelve un objeto con tres propiedades name, type y
max_length. Si max_length es desconocido o no se puede obtener es = -1.

Por Ejemplo:

$recordset = $conn->Execute("select fecha from tabla");


$f0 = $recordset->FetchField(0);

$f0->name contiene 'fecha', $f0->type contiene 'date'.

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).

C: tipos character y varchar


X: text o long character (ej. Para más de 255 bytes ).
B: imagen blob o binary
D: date
T: timestamp
L: logical (boolean)
I: integer
N: numeric (float, double, money)

Tomando el ejemplo de arriba:

$recordset = $conn->Execute("select fecha from tabla");


$f0 = $recordset->FetchField(0);

Autor: Ing. Oscar R. Espeche


112
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

$type = $recordset->MetaType($f0->type, $f0->max_length);


print $type; /* debe imprimir 'D' por fecha*/

Limites de selección en una SQL

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.

Soporte de sesiones PHP4


ADODB soporta sesiones PHP. Puede guardar variables de sesiones en una base de datos
para asegurar escalabilidad.

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.

Autor: Ing. Oscar R. Espeche


113
PHP,MySQL y E-COMMERCE Diseño de aplicaciones con PHP y MySQL

Otro ejemplo

<?
include('adodb.inc.php'); //Este es un archivo con los datos que necesita el programa para reconocer adodb

$conn = &ADONewConnection('mysql'); Aquí el tipo de BD


$conn->PConnect("localhost", "alumno1", "alumno", "tabla1");Conexión con la BD

if (!$DB)
print "No se realizó la conexión";
else{
$query= "select * from tabla1";
$query.= "where nombre like '%$nombre%'";

$datos = $DB->Execute("$query"); /*Ejecutamos el query*/

$numFilas = $datos->RecordCount(); /* contamos el total de registros de resultado */

for ($i=0;$i<=$numFilas;$i++){

/* Comenzamos a extraer de la BD los registros */


$nombre= $datos->fields["nombre"];
$appat = $datos->fields[apellido"];

print " $i. Nombre:$nombre $appat";


}

$datos->Close(); //opcional
$conn->Close(); //opcional
}
?>

Autor: Ing. Oscar R. Espeche


114

Vous aimerez peut-être aussi