Estás en Principal | Crear Sistema Encuestas |
Ver Comentarios | 7-11-2009
Por Dago Gonzalez
En este tutorial crearemos un foro desde cero aprendiendo a separar la programación del diseño, y modularizando nuestra aplicación para que sea simple de configurar y de adaptar.
Primero y antes que nada, debemos preparar la tabla en la base de datos que contendrá todos los temas de nuestro foro. Lo que esta tabla tendrá, es la información de nuestros mensajes, el autor del mismo, y otros datos que servirán para identificar a que Tema pertenece un mensaje. Pero mejor, veamos la estructura propuesta:
create database `mibasedatos`; use `mibasedatos`; CREATE TABLE foro ( id int(7) NOT NULL auto_increment, autor varchar(200) NOT NULL default '', titulo varchar(200) NOT NULL default '', mensaje blob NOT NULL, fecha datetime NOT NULL default '0000-00-00 00:00:00', respuestas int(11) NOT NULL default '0', identificador int(7) NOT NULL default '0', ult_respuesta datetime default NULL, KEY id (id) ) TYPE=MyISAM; INSERT INTO foro VALUES (1,'conio','quien precipita el frio?','yo sé quien precipita el frio, es el precipitado calor','2006-07-27 01:00:00',2,0,'2006-07-27 01:00:00'); INSERT INTO foro VALUES (2,'pirulina','os acordais de pirulin pinpon? io no','creo que si me acuerdo que no recuerdo quien fue se conio','2006-07-28 00:14:47',3,0,'2006-07-28 00:14:47');
Veamos en detalle que campos tendrá nuestra tabla de Foros:
La sentencia SQL anterior, pueden guardarla en un archivo.sql y correrla en su base de datos desde el phpMyAdmin. Una vez que hayan creado la tabla en su base de datos, entonces podemos avanzar al siguiente paso.
Antes de ponernos a programar cualquier parte del foro, vamos a encargarnos de hacer un pequeño script que realice una tarea que vamos a repetir mucho, y que es conectarnos a la base de datos. Este script lo incluiremos en cada página en la que tengamos que acceder a la base de datos:
Ejemplo de la pagina de configuracion.inc.php<?php $host = "localhost"; $usuario = "miusuario"; $password = "mipassword"; $base = "mibasedatos"; $con = mysql_connect($host, $usuario, $password); mysql_select_db($base, $con); ?>
Cómo vemos, no hay gran ciencia en este script, tan solo unas variables conteniendo la configuración de nuestra base de datos, y el código mínimo y necesario para conectarnos y guardar el recurso de conexión en una variable $con que luego utilizaremos cuando hagamos nuestras consultas.
Para aquellos que no sepan que es un Template, les recomiendo que lean artículos al respecto , por lo menos para que tengan una idea de que son y para que sirven.
Ahora, mi idea al utilizar templates, fue la de que los usuarios, pudieran modificar a su gusto el aspecto del foro, sin por ello tener que tocar el código de la aplicación. Lo que haremos en este caso es utilizar archivos .html que dentro contendrán solo diseño ( o sea, código HTML ) y en los lugares en los que deseemos colocar contenido "dinámico", utilizaremos el formato simple para mostrar el contenido de variables, esto es : <?=$variable?>.
Para "interpretar" un template, primero lo leemos en memoria utilizando la función file() y luego utilizaremos una simple función a la que le pasaremos como parámetro el template y las variables que hay que reemplazar. Para muestra, basta un botón:
Ejemplo de la pagina de ejemplo.htmlNombre: <b><?=$nombre?></b><br> Edad : <b><?=$edad?></b><br> Domicilio : <?=$domicilio?> <hr>
<?php
function mostrarTemplate($tema, $variables)
{
//var_dump($variables);
extract($variables);
eval("?>".$tema."<?");
}
$agenda = array(
"0" => array("nombre"=>"Panchita", "edad"=>"69", "domicilio"=>"Ya tu sabes #69"),
"1" => array("nombre"=>"Juanita", "edad"=>"17", "domicilio"=>"Gemir Thiago 18"),
"2" => array("nombre"=>"Sarita", "edad"=>"15", "domicilio"=>"Pathy nhoay f.u.")
);
$tpl = implode("", file("ejemplo.html"));
foreach($agenda as $registro)
{
mostrarTemplate($tpl, $registro);
}
?>
Aquí vemos que tenemos en un array, los mostramos basándonos en un simple template. La función mostrarTemplate toma como parámetros el contenido del template y un array asociativo con los valores a reemplazar. La función de PHP extract() se encarga de pasar estos valores al ámbito en el que se llama la función, en este caso, el ámbito de la función. Por lo que si tenemos un arreglo del tipo $a = array("clave" => "valor"), al ejecutar extract($a), entonces pasaremos a tener una variable disponible, de nombre $variable y con "valor" como contenido. Luego, la función eval() se encarga del resto, o sea, de ejecutar todo el código (el del Template) que se le pasa como parámetro.
Algunos se preguntarán, porqué no hacemos simplemente un "include" ? La respuesta es muy siemple. Eficiencia. La función include implica un acceso a disco, lo cual la hace bastante "costosa" en términos de eficiencia. Así que leyendo el template 1 sola vez en memoria, y luego utilizándolo varias veces, hacemos un mejor uso de los recursos.
Teniendo estos temas en cuenta, es que podemos seguir ahora con el desarrollo del Foro.
Ya teniendo las bases de nuestro foro, el diseño de la tabla en la base de datos y conociendo como funciona nuestro sistema de templates, podemos comenzar a crear la primera página, en la que mostraremos todos los temas del foro:
Ejemplo de la pagina de index.php<?php
require('configuracion.inc.php');
require('funciones.php');
include('header.html');
/* Pedimos todos los temas iniciales (identificador==0)
* y los ordenamos por ult_respuesta */
$sql = "SELECT id, autor, titulo, fecha, respuestas, ult_respuesta ";
$sql.= "FROM foro WHERE identificador=0 ORDER BY ult_respuesta DESC";
$rs = mysql_query($sql, $con);
if(mysql_num_rows($rs)>0)
{
// Leemos el contenido de la plantilla de temas
$template = implode("", file("temas.html"));
include('titulos.html');
while($row = mysql_fetch_assoc($rs))
{
$color=($color==""?"#5b69a6":"");
$row["color"] = $color;
mostrarTemplate($template, $row);
}
}
include('footer.html');
?>¿Eso es todo? Si, eso es todo. Ahora revisemos paso a paso lo que hace el script. Primero tenemos una serie de requires e includes. El primero incluye el primer Script que hicimos, que realiza la conexión a la base de datos. El segundo, incluye un archivo.php que contiene funciones importantes del foro, como por ejemplo, mostrarTemplate. El tercero, incluye un header genérico que utilizaremos para darle a todas nuestras páginas, un diseño similar. Allí podremos colocar un logo del sitio, links importantes, banners, etc.
$sql = "SELECT id, autor, titulo, fecha, respuestas, ult_respuesta ";
$sql.= "FROM foro WHERE identificador=0 ORDER BY ult_respuesta DESC";
$rs = mysql_query($sql, $con);
if(mysql_num_rows($rs)>0)
{Aquí lo que hacemos es ejecutar un query en la base de datos, que nos traerá todos los mensajes que son iniciadores de un tema, o sea, cuyo identificador esté en cero. El resto de los mensajes, que sean respuestas a un tema en particular, tendrán en el campo identificador el valor del mensaje al que responden. A estos temas, le pedimos a la base que los ordene por la fecha de última respuesta, de manera descendente, así en nuestro foro, tendremos los mensajes más recientes primero. También realizamos una decisión, solo mostraremos los temas de nuestro Foro si la cantidad de filas recuperadas desde la base, son mayores a 0.
Luego, dentro del While principal del programa, se tiene:
// Leemos el contenido de la plantilla de temas
$template = implode("", file("temas.html"));
include('titulos.html');
while($row = mysql_fetch_assoc($rs))
{
$color=($color==""?"#5b69a6":"");
$row["color"] = $color;
mostrarTemplate($template, $row);
}Aquí comenzamos a trabajar por primera vez con los templates. Primero leemos el contenido del template en memoria y lo guardamos dentro de la variable $template. También incluimos un archivo, que contiene una fila de la tabla de Temas, con los títulos de las celdas. EL resto ya lo vimos anteriormente, llamando a la función mostrarTemplate mostramos los datos de cada tema.
Finalmente, solo agregamos otro archivo HTML, con el código para cerrar la página y mostrar algún que otro mensaje de Copyright (o lo que queramos poner). Con esto ya tenemos nuestra página inicial del Foro, mostrando los temas que haya. Ahora, vamos a crear el formulario necesario para ingresar nuevos temas o para responder algún tema existente.
Bueno, en estos tiempos hay que ahorrar lo más que se pueda y esto se aplica a casi todo. Así que, haciendo caso al dicho, podemos utilizar el MISMO formulario para crear un nuevo tema y para contestar un tema en particular. Esto lo vamos a lograr, pasando una variable por el URL, indicando que estamos citando un mensaje anterior, sacando de la base de datos el mensaje que citaremos, y completando el formulario con esos datos. Si la variable no está presente, entonces no hacemos nada y mostramos el formulario.
Ejemplo de la pagina de respuesta.php<?php
require('funciones.php');
$id = $_GET["id"];
$citar = $_GET["citar"];
$row = array("id" => $id);
if($citar==1)
{
require('configuracion.inc.php');
$sql = "SELECT titulo, mensaje, identificador AS id FROM foro WHERE id='$id'";
$rs = mysql_query($sql, $con);
if(mysql_num_rows($rs)==1) $row = mysql_fetch_assoc($rs);
$row["titulo"] = "Re: ".$row["titulo"];
$row["mensaje"] = "[citar]".$row["mensaje"]."[/citar]";
if($row["id"]==0) $row["id"]=$id;
}
$template = implode("", file('formulario.html'));
include('header.html');
mostrarTemplate($template, $row);
include('footer.html');
?>En el script vemos como primero capturamos de la URL, las variables $id y $citar, y si ésta última es igual a 1, entonces consultamos en la base de datos toda la información del tema que estamos citando, para agregarlo en el arreglo $row, que luego será pasado al template. Noten como al titulo del mensaje, le anteponemos la cadena "Re:", indicando que es una respuesta, y como al cuerpo del mensaje, si estamos citando, lo rodeamos por un tag [citar] y [/citar]. Esto lo veremos más adelante.
Ejemplo de la pagina de formulario.html<table width="90%" border="0" cellspacing="2" cellpadding="2">
<form name="f" action="agregar.php" method="post">
<input type="hidden" name="identificador" value="<?=$id?>">
<tr>
<td width="30%" align="right">Autor </td>
<td><input type="text" name="autor"></td>
</tr>
<tr>
<td width="30%" align="right">Titulo</td>
<td><input type="text" name="titulo" value="<?=$titulo?>"></td>
</tr>
<tr>
<td width="30%" align="right">Mensaje</td>
<td><textarea name="mensaje" cols="50" rows="5"><?=$mensaje?></textarea></td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" name="Submit" value="Enviar Mensaje"></td>
</tr>
</form>
</table>Aquí vemos como colocamos las variables dentro de los atributos "value" de los inputs y el textarea. También podemos ver como tenemos un campo escondido, llamado "identificador", que solo tendrá un valor asignado, cuando estemos respondiendo a un mensaje, pero que no existirá cuando sea un mensaje nuevo. Solo queda ver el script que se encarga de grabar el mensaje en la base de datos, agregar.php.
Ejemplo de la pagina de agregar.php<?php
require('configuracion.inc.php');
$autor = $_POST["autor"];
$titulo = $_POST["titulo"];
$mensaje = $_POST["mensaje"];
$ident = $_POST["identificador"];
//Hacemos algunas validaciones
if(empty($autor)) $autor = "Anónimo";
if(empty($titulo)) $titulo = "Sin título";
// Grabamos el mensaje en la base.
$sql = "INSERT INTO foro (autor, titulo, mensaje, identificador, fecha, ult_respuesta) ";
$sql.= "VALUES ('$autor','$titulo','$mensaje','$ident',NOW(),NOW())";
$rs = mysql_query($sql, $con) or die("Error al grabar un mensaje: ".mysql_error);
$ult_id = mysql_insert_id($con);
/* si es un mensaje en respuesta a otro
actualizamos los datos */
if(!empty($ident))
{
$sql = "UPDATE foro SET respuestas=respuestas+1, ult_respuesta=NOW()";
$sql.= " WHERE id = '$ident'";
$rs = mysql_query($sql, $con);
Header("Location: foro.php?id=$ident#$ult_id");
exit();
}
Header("Location: index.php");
?>En este script, luego de tomar las variables desde el formulario (con el método POST), primero verificamos que exista un nombre de autor y el título del mensaje, caso contrario le asignamos un valor por defecto.
A continuación, grabamos el mensaje en la base, y obtenemos, mediante la función mysql_insert_id(), el último id autoincremental que le corresponde a este registro. ¿Para qué? Simple. Si este mensaje que acabamos de grabar es el primero del tema, no necesitamos hacer nada, pero si es un mensaje en respuesta a otro ( esto lo averiguamos preguntando por el valor de $identificador), entonces tenemos que actualizar ese primer mensaje, indicando que tiene una respuesta más, y cambiando la fecha y hora del último mensaje. De esa manera, nos aseguramos que tenemos bien ordenado el foro, con los temas con nuevos mensajes primero. Finalmente, dependiendo del caso, redirigimos al usuario al home del foro, o a la respuesta que acaba de ingresar.
Ya solo nos queda un último paso, y es el de crear la página que mostrara un tema y todas las respuestas que haya en él. Para ello, vemos como en el home del foro, llamamos a un script foro.php y le pasamos el id del tema que queremos ver. Luego, solo tenemos que obtener de la base el o los temas, en los que el id sea igual al que pasamos, o que el identificador (el campo que indica que ese mensaje es en respuesta a cierto tema) sea igual al identificador, los ordenamos por fecha y listo, foro al dente.
En este caso, el template que utilizaremos para mostrar cada uno de los mensajes, será una tabla con todos los datos necesarios: el autor del mensaje, el título, la fecha del mensaje, el mensaje en si mismo. Pero también agregaremos dos detalles. Primero, un link hacia el formulario que creamos antes, de modo que un usuario pueda citar un mensaje en particular, y segundo, un Anchor (o Ancla) para que al responder a un mensaje, se pueda acceder directamente al mismo por su id en la base de datos.
Ejemplo de la pagina de post.html<table width="90%" border="0" align="center" cellpadding="2" cellspacing="2"> <tr bgcolor="<?=$color?>"> <td width="25%" valign="top"> <b><a name="<?=$id?>"><?=$autor?></a></b><br> <font size="-2">Enviado el : <?=$enviado?></font> </td> <td> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td><strong><font size="-1"> <?=$titulo?> </font></strong> </td> <td width="10%" align="right"> [ <a href="respuesta.php?id=<?=$id?>&citar=1">CITAR</a> ]</td> </tr> </table> <hr align="center" width="100%" size="2" noshade> <?=$mensaje?></td> </tr> <tr> <td colspan="2" height="5"></td> </tr> </table>
Ahora, veamos el código PHP que utilizaremos para mostrar este template:
Ejemplo de la pagina de foro.php<?php
require('configuracion.inc.php');
require('funciones.php');
$id = $_GET["id"];
if(empty($id)) Header("Location: index.php");
$sql = "SELECT id, autor, titulo, mensaje, ";
$sql.= "DATE_FORMAT(fecha, '%d/%m/%Y %H:%i:%s') as enviado FROM foro ";
$sql.= "WHERE id='$id' OR identificador='$id' ORDER BY fecha ASC";
$rs = mysql_query($sql, $con);
include('header.html');
if(mysql_num_rows($rs)>0)
{
include('titulos_post.html');
$template = implode("", file('post.html'));
while($row = mysql_fetch_assoc($rs))
{
$color=($color==""?"#5b69a6":"");
$row["color"] = $color;
//manipulamos el mensaje
$row["mensaje"] = nl2br($row["mensaje"]);
$row["mensaje"] = parsearTags($row["mensaje"]);
mostrarTemplate($template, $row);
}
}
include('footer.html');
?>Como siempre, incluimos la conexión a la base de datos, el archivo de funciones y validamos de que exista la variable $id, ya que de lo contrario, nada podríamos hacer y nuestro foro fallaría. Si quieren más información sobre esta otras funciones, pueden visitar y consultar el manual de mySQL.
Lo más destacado en este script que podemos ver, son dos transformaciones que le hacemos al mensaje, antes de enviarlo al template. Como vemos, primero utilizamos la función de PHP nl2br(), que convierte todos los saltos de linea, en tags <br />, de esa manera, los saltos que un usuario ingrese en el textarea, serán agregados correctamente al mostrar el mensaje. Luego, vemos como llamamos a la función parsearTags(). ¿Qué hace esta función? Veamos:
Ejemplo de la pagina de funciones.php<?php
function mostrarTemplate($tema, $variables) {
extract($variables);
eval("?>".$tema."?"); //ATENCION!!! debes AGREGAR el signo < antes del segundo signo de interrogación de esta línea
}
function parsearTags($mensaje) {
$mensaje = str_replace("[citar]", "<blockquote><hr width='100%' size='2'>", $mensaje);
$mensaje = str_replace("[/citar]", "<hr width='100%' size='2'></blockquote>", $mensaje);
return $mensaje;
}?>Dentro de esta función, podemos agregar todas las modificaciones que queremos realizarle al mensaje, antes de mostrarlo en el Foro. En el ejemplo, vemos como hemos implementado el uso de un tag propio, [citar]. El mismo, dentro de la función, será reemplazado por el código HTML necesario para destacar el citado de un mensaje, todo esto gracias a la función str_replace() de PHP (más info en el manual). Este es el tag [citar] que se agrega automáticamente, y que notamos cuando respondíamos un mensaje.
Esta función, pueden personalizarla de la manera que deseen, agregando todos los tags que quieran, para ofrecerles a sus usuarios la libertad de darle formato a sus mensajes. Podrían, por ejemplo, agregar un nuevo tag, para poner palabras en negritas, o quizás alguna expresión regular que convierta automáticamente cualquier URL presente en el mensaje, en un link. Los límites son los de su imaginación.
Realizar nuestro primer foro es no es muy dificil, si sabemos utilizar mínimamente mySQL y PHP (más bien, tan solo ciertas funciones muy útiles del PHP). En estas pocas líneas aprendimos:
atte. Dago2007
fin
Nuestras Encuestas: Participa!!