Creando un sistema de blog propio [PHP]

Mucha gente dice a veces… para qué re-inventar la rueda?…y esto con referente a modelos estructurados de programación en los que siempre hay algunos aventureros inventando cosas sólo para que se les felicite o reconozca… bueno, esta vez yo tengo una razón un poco más de peso para re-inventar la rueda: INVESTIGACIÓN … (aunque claro, a veces hay gente hincha que exagera con eso y en vez de investigar lo que quieren es crear algo para intentar hacer competencia con lo ya existente… ¬¬, en ese caso, prefiero usar librerías conocidas), y bueno, esta vez quiero compartir en este post un proyecto que me mantuvo entretenido en lo que no he tenido internet el pasado mes y que aparte sirvió de buen “desestresador”, “desaburridor” y del cual no podía decir que estaba perdiendo el tiempo; un sistema de blog a partir de mis conocimientos básicos de PHP y MySQL.

En verdad, no es la gran cosa, no voy a vender gatos por liebres, ni decir que usé algo fuera de lo común que va a pegar en el mundo de la programación, y que muy aparte que exista WordPress, que lo recomiendo, esto quise compartirlo para que no se pierda en la bastedad del mundo de los 0 y 1, porque a fin de cuentas, todo el mundo puede tener un blog sin más personalización que hacer un par de clics (como en Blogger) o hacer algunas que otras modificaciones con etiquetas ya existentes a nivel código (WordPress) y bueno, después de probar tal o cual sistema, llegue a la conclusión -personal- de que no hay blog más personal que el que hecho por ti mismo desde 0 (esto es debatible, sólo es mi punto de vista personal ojo). Aunque bueno, es una experiencia rara XD… para proyectos serios obviamente usaría WordPress… pero vamos a ver qué tal va esto de crear tu propio sistema de blog!

Me di cuenta que, los blogs tienen cosas en común, y bueno, eso es obvio, el hecho está en que puedes crear un blog básico con unos cuantos archivos y algunas tablitas en MySQL  (que ni si quiera me preocupe en vincular con PK, FK, Joins, vistas, etc y eso porque no me gusta mucho esas cosas), que cumplan determinadas funciones básicas como un index.php, un archivo que muestre los post y comentarios (sí!… un solo archivo para mostrar de forma individual todos los post que tengas) y de preferencia un archivo donde almacenes funciones globales que crees que vas a utilizar en más de un archivo (en todo caso esto modulariza un poco el sistema) y ya el resto lo dejo a tu imaginación.

Pero bueno, vamos con lo técnico del sistema que hice, quizás a alguien le pueda funcionar…

Nota: Los códigos que veras son un alcance del sistema en sí, no es un tuto general de como hacer un blog con dos o tres archivos, sino pequeños avances de como es que hice esto en específico caso.

Primero habrá que esquematizar un poco el Sistema!, es decir, al ser dependiente de una base de datos tendremos que crear algunas tablitas en una base de datos que para esta ocasión llamaré “Blog”:

Una Tabla Post que en sí será los datos de los post! Con la siguiente estructura: ID_post (para poner un id único a cada post), contenido_post, fecha, autor, titulo, numComents_post (esto es el número de comentarios que tiene el post), y un campo llamado Borrador_post (yo lo usé para identificar si es borrador o ya esta publicado, tinyint vendría a usarse como boolean, sólo con 0 o con 1).

BLOG_POST

Una Tabla Comentario: con casi los mismos atributos salvo que aquí le puse además el ID_post para identificar a que post pertenece cada comentario, con los inserts se especifica a que post se manda el comentario y obviamente cada comentario tiene un especificador único, además de un identificador de votos de spam que decidí poner hace poco nomás, que consiste en que los usuarios califiquen si es SPAM y así se almacenen votos de SPAM, cosa que el admin sólo borra el comentario de acuerdo a los votos de SPAM recibidos (aunque no lo tengo terminado aún).

BLOG_COMENTARIO

Y para efectos de Logueo e identificación una tabla que almacene usuarios (Usuario), yo no llegue a implementar o darle importancia a lo del multiusuario (con lo que, deberíamos identificar rangos y permisos, y se hacen más tablas, o más campos quizás) así que todos los usuarios que estén en esta tabla podrán postear de la misma manera.

BLOG_USUARIO

Eso sí, logré hacer algunas otras tablas, como una para un feedback, otra para almacenar opciones y estoy pensando en poner algunas otras dos para agregar funcionalidades como el sidebar, categorías, etiquetas o así. Pero por el momento, supongo que estas tres tablas bastarán para hacer un blog básico.

Ahora yendo al código en PHP una vez que ya tenemos nuestras tablas he de decir que resultaron demasiados archivos (para lo básico que quiero que sea), quizás porque “tape huecos” del sistema a la volada (el CSS, los estilos y algo del Javascript lo hice en 15 a 20 minutos ¬¬). Pero lo principal está entendible.

Bueno, para comenzar, debemos tener, como mínimo:

  • Un archivo index.php
  • Un archivo que muestre cada post, que yo en el sistema llamé ShowPost.php
  • Un archivo de funciones, funciones.php
  • Y si quieres unos archivos que sirvan como panel de control para tener un formulario donde escribir los post! (digo “si quieres” porque esto es un poco tedioso y aún no tengo terminado del todo tal panel, me faltan algunas cosas como poder validar los acentos con Javascript, y sin esto, tendrías que postear directamente insertando datos en MySQL).

Comenzaremos por el archivo funciones.php, y empezamos por las funciones de conexión:

funciones.php:

//Comenzamos con las funciones de conexion!!! conectar() y desconectar()
//para no andar invocando a cada rato todos los parametros especificados de la base de datos.

function conectar()
 {
 // VARIABLES DE CONEXION:

 ///////////////////////////////////////////////
 $bd = "bd"; //el nombre de la base de datos
 $user= "user"; //el usuario de mysql
 $pass = "1234"; //el password de mysql (dejarlo en "" si no hay password
 $server = "server"; //el servidor de la base de datos!!
 ///////////////////////////////////////////////

 $con = mysql_connect($server, $user, $pass); //esto conecta a la base de datos

 mysql_select_db($bd);

 if($con == false){
header("Location: install/aviso.php?e=1");
//se va por aqui si no hay conexion o hay errores.
 }

return $con;
 }

 function desconectar($con)
 {
mysql_close($con); //desconecta toda instancia de mysql
 }

Tambien especificamos funciones básicas como mostrar título, mostrar descripción, etc.

funciones.php:

function MostrarTitulo($con){
 //lo jala de la base de datos y lo muestra en la pagina principal y otros lados!
 $sql ='SELECT * FROM blog_opciones WHERE nombre_opcion = "Nombre";';

 $result = mysql_query($sql, $con);

 while($row = mysql_fetch_array($result))
    {
    echo $row[2];
    }
    //si no hay una tabla opciones puedes hacer que imprima directamente un titulo de tu preferencia
    //echo "Mi titulo"; //asi solo tendras que cambiar este archivo
    //y no todas las plantillas en donde use esta funcion
}

 function MostrarDescripcion($con){
 //Muestra el subtitulo del blog
 $sql ='SELECT * FROM blog_opciones WHERE nombre_opcion = "Descripcion";';
 $result = mysql_query($sql, $con);

   while($row = mysql_fetch_array($result))
   {
     echo $row[2];
   }
//lo mismo de la funcion anterior si no tienes una tabla opciones
 }

 function MostrarKeywords($con){
 //palabras clave
 $sql ='SELECT * FROM blog_opciones WHERE nombre_opcion = "Palabras_Clave";';
 $result = mysql_query($sql, $con);

   while($row = mysql_fetch_array($result))
   {
    echo $row[2];
   }

//lo mismo que las otras dos funciones si no tienes tabla opciones
 }

Y bueno, asi podemos ir agregando funciones globales a nuestro sistema esperando usarlas más de una vez, no creí conveniente agregar lo de la tabla opciones para hacerlo más facil, ya si quieren verlo, al final del post está todo el código fuente que tengo hasta la fecha o pueden ver el funciones.php completo que tengo hasta el momento de escribir este post, desde aquí

Ahora vamos con un prototipo del archivo index.php:

index.php:

<?php  session_start();
 include("funciones.php"); //archivo de funcionamientos

  $con = conectar();
?>

<?php include("header.php"); //es un archivo que contiene el código header comun de una web html, lo hice para ahorarme código entre plantillas ?>
<br />
<?php
 $num_post_x_page = GetNumeroPostxPage($con); //chekear archivo funciones.php del codigo fuente
 //esto sirve para especificar cuantos post deberían ser por página

 $sql ='SELECT * FROM blog_post where Borrador_post=0 ORDER BY ID_post DESC;';
 //es un select ordenado de abajo hacia arriba para visualizar primero el post mas nuevo y que no sea borrador!

 $result = mysql_query($sql, $con);
 $cant = mysql_num_rows($result);

 if($cant == 0){
 //si la consulta obtiene 0 filas
   echo '<p align="center">No hay posts por el momento</p>';
 }
 else{
 $i =0; //contador de vueltas
 while($row = mysql_fetch_array($result))
 {
 ?>
 <div>
 <table width="75%" border="0" align="center" bordercolor="#000000">
 <tr>
 <td width="17%" height="10"><img src="images/pencil.png" align="absmiddle" />Escrito Por <?php echo $row[3]; ?></td>
 <td width="83%" rowspan="2" valign="bottom"><div><h2><a href="ShowPost.php?p=<?php echo $row[0]; ?>"/><?php echo $row[4]; ?></a></h2>
 </div>                </td>
 </tr>
 <tr>
 <td height="11"><img src="images/time.png" align="absmiddle" /><?php echo $row[2]; ?></td>
 </tr>
 <tr>
 <td valign="top"><a href="ShowPost.php?p=<?php echo $row[0]; ?>" />Comentarios: <?php echo $row[5]; ?></a></td>
 <td  valign="top"><font face="Verdana" size="2"><?php echo $row[1]; ?></font><hr color="#000000" size="1" noshade align="right" width="40%"/>
 <span><a href="ShowPost.php?p=<?php echo $row[0]; ?>">Haga Clic aqu&iacute; para leer Completo y comentar si desea</a></span></td>
 </tr>
 </table>
 </div>
 <br />
 <?php
 $i++;

 if($i == $num_post_x_page) //EL NUMERO DE POST A MOSTRAR
   {
    $_SESSION["PAGES"]=1; //registra en sesion que la paginacion existe!
    break;
   }
  }
 }?>

<?php
 if(@$_SESSION["PAGES"]==1){
?>
 <br />
 <p align="center"><a href="page.php?pg=2">Siguiente P&aacute;gina <img src="images/next.gif" border="0" width="16" height="16" /></a></p>
 <br />
 <?php
    $_SESSION["PAGES"] = 0; //esto borra la paginacion si es que hay algun error
 }
?>
<?php  include("footer.php"); //lo mismo que el header.php ?>

<?php desconectar($con); ?>
</body>
</html>

Ahora bien, si se fijan, por ahi hay algunas referencias al archivo ShowPost.php que mencioné mas arriba pero aparte se le pasa un parametro “p” con un número como valor, pues bien, lo que hago es que el archivo reconozca ese valor, y muestre el post con el id de ese valor, con sus respectivos comentarios de acuerdo a como estén asociados con el post, y si no se le manda ningún valor lo parseamos con una funcion error($cadena) que está especificada en el archivo funciones.php (lo pueden ver en el código fuente)

ShowPost.php:

<?php  session_start();
 include("engine/funciones.php");

@$idpost = $_GET["p"]; //obtiene el id del post del parametro que se le paso!!!
$con = conectar();

ComprobarPost($con, $idpost);
//ESTO COMPRUEBA QUE EL POST EXISTA... SINO LANZA UN MENSAJE!!!
//verificar funciones.php para mayor entendimiento
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<title><?php MostrarTituloPost($con, $idpost); //verificar funciones.php ?> | <?php  MostrarTitulo($con); ?></title>
<link href="CSS/Style.css" rel="stylesheet" type="text/css" media="screen"> <!-- SCRIPT CSS PARA EL DISENO-->
<script language="javascript" type="text/javascript" src="JS/funciones.js"></script> <!-- SCRIPT JS-->
<meta name="keywords" content="<?php MostrarKeywords($con); ?>"><!-- PALABRAS CLAVE--></head>

<body>
<h1 align="center"><a href="index.php"><?php  MostrarTitulo($con); ?></a></h1>
<h5 align="center"><?php  MostrarDescripcion($con); ?></h5>
<div align="center"><?php MostrarMenu(); ?></div>
<br />
<div>
<table width="70%" border="0" align="center" bordercolor="#000000">
 <tr>
 <td><h1><?php MostrarTituloPost($con, $idpost); ?></h1><hr color="#000000" size="1" noshade /></td>
 </tr>
 <tr>
 <td><font face="Verdana" size="2">
 <?php MostrarContenidoPost($con, $idpost); ?>
 </font></td>
 </tr>

 <tr>
 <td colspan="2"><div align="right">
 <p><strong>Compartir:</strong> <a href="http://www.twitter.com/home?status=http://<?php Permalink($con);?>">Twitter</a> | <a name="fb_share" type="button_count" href="http://www.facebook.com/sharer.php">Compartir</a><script src="http://static.ak.fbcdn.net/connect.php/js/FB.Share" type="text/javascript"></script></p>
 </div></td>
 </tr>
 <tr>
 <td width="42%" colspan="2">
 <div><em> <img src="images/time.png" align="absmiddle" /> Esta entrada fue editada por &uacute;ltima vez por <u><?php MostrarAutorPost($con, $idpost); ?></u> @ <u><?php MostrarFechaPost($con, $idpost); ?>
 </u></em><u></u>      </div>
 </tr>
</table>
</div>
<br />
<p align="center"><b><?php MostrarCantOpiniones($con, $idpost); ?></b></p>
<?php //OBTENIENDO LOS COMENTARIOS!!!
 $sql ='SELECT * FROM blog_comentarios WHERE ID_post = "'.$idpost.'" order by ID_comentario ASC;';
 $result = mysql_query($sql, $con);
 $cant = mysql_num_rows($result);
 $c= 0;
 if($cant == 0){
 echo '<center><div>NO HAY COMENTARIOS</div></center>';
 }else{

 while($row = mysql_fetch_array($result))
 {
    $c = $c+1; //CONTADOR DE COMENTARIOS!(pone el numero a cada comentario en formato #1, #2, etc)

 if($row[4]==NULL){?>
 <div>
 <table width="65%" border="0" align="center">
 <tr>
 <td><div><input id="inreplyto" type="button" onClick="return inreplyto(<?php echo $c;?>, '<?php echo $row[2] ?>')" name="btnReplyComentsinLink" value="#<?php echo $c;?>">
 <font color="#000000"><?php echo $row[2] ?></font> <small>Dijo ( @ <?php echo $row[5]?>)</small>:</div></td>
 </tr>
 <tr>
 <td><?php echo $row[6]; ?></td>
 </tr>
 <tr>
 <td>
 <input id="btnSPAM1" onclick="return spam(this, '<?php echo $row[0]; ?>')" type="button" name="btnSPAM1" value="es SPAM?" /></td>
 </tr>
 </table><br />
 </div>
 <?php }else{?>
 <div>
 <table width="65%" border="0" align="center">
 <tr>
 <td><div><input id="inreplyto" type="button" onClick="return inreplyto(<?php echo $c;?>, '<?php echo $row[2] ?>')" name="btnReplyComentConLink" value="#<?php echo $c;?>">  <a target="_blank" href="http://<?php echo $row[4] ?>"><?php echo $row[2] ?></a> <small>Dijo ( @ <?php echo $row[5] ?>)</small>: </div></td>
 </tr>
 <tr>
 <td><?php echo $row[6] ?></td>
 </tr>
 <tr>
 <td>
 <input id="btnSPAM2" onclick="return spam(this, '<?php echo $row[0]; ?>')" type="button" name="btnSPAM2" value="es SPAM?" /></td>
 </tr>
 </table>
</div>
 <br />
 <?php }
 }
 }

?>
 <hr color="#000000" />
 <div align="center"><strong><em>Desea opinar? &Omega; :</em></strong></div>
 <p align="center">
 <?php  echo @$_SESSION["Comentario"];
$_SESSION["Comentario"] =""; ?>
 </p>
 <?php if(@$_SESSION["Conectado"]==1){?>
 <form name="frmComentario" method="post" action="EnviarComentario.php" onSubmit="return validarFechaComentario(this)">
 <div align="center"> <font color="yellow">Logueado como
 <?php  echo $_SESSION["UsuarioLogueado"]; ?>
 </font><a href="CerrarSesion.php">(Cerrar Sesi&oacute;n)</a></div>
 <?php }else{?>
 <form name="frmComentario" method="post" action="EnviarComentario.php" onSubmit="return validarComentario(this)">
 <table width="43%" border="0" align="center">
 <tr>
 <td colspan="2">Sin insultos a otros usuarios, y sin salirse del tema del post.
 <hr noshade color="#000000" /></td>
 </tr>
 <tr>
 <td width="50%">Nombre:</td>
 <td width="50%"><input name="txtNombre" type="text" id="txtNombre" value="<?php echo @$_SESSION["NOMBRE"]; ?>" size="45"></td>
 </tr>
 <tr>
 <td>Email (No se muestra):</td>
 <td><input name="txtEmail" type="text" id="txtEmail" value="<?php echo @$_SESSION["EMAIL"]; ?>" size="45"></td>
 </tr>
 <tr>
 <td>Sitio Web (sin http://): </td>
 <td><input name="txtURL" type="text" id="txtURL" value="<?php echo @$_SESSION["URL"]; ?>" size="45"></td>
 </tr>
 </table>
 <input name="spam" type="hidden" value="">
 <?php } ?>
 <p align="center">Su Mensaje:</p>
 <center>
 <table width="46%" border="0">
 <tr>
 <td width="9%">
 <input type="button" name="btnLink" value="Link" onclick="return LinkMsjComentario(this)" />
 <input type="button" name="btnIMG" value="IMG" onclick="return IMGMsjComentario(this)" /></td>
 <td width="91%"><textarea name="txtMsj" cols="70" rows="5" id="txtMsj"></textarea></td>
 </tr>
 </table>
 <p>
 <input type="submit" name="Submit" value="Enviar Comentario">
 </p>
 <p>Quieres expresar tu opini&oacute;n directamente y sin que se muestre aqu&iacute;?<br />
 <a href="contacto.php?subject=Opini&oacute;n en <?php MostrarTituloPost($con, $idpost); ?>">Cliquea Aqu&iacute;</a> para dejar tu feedback acerca del post.<br />
</p>
 </center>
 <input name="fecha" type="hidden">
 <!-- Se genera con el envio -->
 <input name="id" type="hidden" value="<?php  echo $idpost; ?>">
 </form>
 <br>
 <?php include("footer.php");?>
 <?php desconectar($con); //DESCONECTA TODA INSTANCIA DE CONEXION A MYSQL ?>
</body>
</html>

Y bueno, supongo que esas son las principales funciones que mostraré sin que se alargue el post tanto, porque el sistema de por si salio extenso.

Las disculpas del caso por no comentar el código… y ahora que ya hay muchos archivos sale una latasa hacerlo… jeje…

Si no entiendes el código o te ha tentado a entenderlo, verifica con calma el código fuente, ahí esta completo con todos los archivos y cualquier duda que tengas sólo dila con confianza, yo la responderé hasta donde den mis capacidades, total todavia esta en desarrollo el proyecto este, pueden modificarlo, adecuarlo a su gusto, etc etc. Ya que use lo básico de PHP como lo es Sesiones, funciones, includes, y consultas en base de datos, lo demas es sólo decorativo

CÓDIGO FUENTE: Un Rar conteniendo la carpeta de la aplicación web y el backup de la base de datos, puedes importarlo en WAMP o en algún hosting que tengas de sobra :P .

Tambíen lo estoy poniendo a prueba en un hosting gratuito para ver que tal va, no es un blog ya funcionando sino algo para probar el sistema este, puedes pasearte por ahi en:

http://blogdewill.hostzi.com

Y si te animas, deja tu comentario o algo XD, de paso que me ayudas a encontrar errores o mejorarlo, pero por sobre todo, espero que alguien le sirva!

Saludos!!!