Bienvenido a datoweb.com!! En este foro podrás encontrar ayuda sobre diseño y desarrollo web en general. Si quieres formar parte de esta comunidad para pedir ayuda o colaborar ayudando a otros usuarios del foro solo tienes que registrarte desde el siguiente enlace: Registrarse en el Foro

Sistema de etiquetas o tag cloud

Hola a todos y todas,

En éste tema les traigo un aporte que particularmente, cuando quise aprender a hacerlo, se me hizo complicado encontrar uno que explicara bien como hacerlo. Se trata de una "Nube de Etiquetas" o "Tag Cloud".

Las nubes de etiquetas consisten en agrupar palabras (etiquetas, tags) y mostrarle al visitante de la web cuales son las etiquetas más usadas, usando también estilos que permiten visualizar mejor cual tiene mayor actividad y cual tiene menor actividad. Empecemos.

Lo primero será crear una tabla en la base de datos, en esa tabla serán insertadas las palabras que serán nuestras etiquetas. Algo sencillo, en mi caso son solo 3 columnas: id (int, primary, auto increment), tags (varchar, UNIQUE), frecuencia (int).

O sea,
id será de tipo int, con índice primario y auto incrementado.
tags será de tipo varchar, con índice único.
frecuencia será de tipo int.

¡Es importante que tags sea de índice único!

Una vez tenemos la tabla creada, se necesita un formulario que inserte las palabras.
<form action="procesar.php" method="post" name="insertar">
      <input type="text" name="texto" required>
      <br>
      <input type="submit" value="Insertar">
</form>
Bien, ese formulario irá donde quieras pero recuerda colocar la ruta correcta en el action.

Ahora, en la página procesar.php iría lo siguiente.

procesar.php
<?php
require_once('connection/config.php');
$conectar;
$basededatos;
$Tags = $_POST["texto"];
if (!empty($Tags)) {
	$Etiqueta = explode(",",$Tags);
	foreach ($Etiqueta as $Tag) {
		$sql= sprintf("INSERT INTO tabla (tags, frecuencia) VALUES ('$Tag', 1) ON DUPLICATE KEY UPDATE frecuencia = frecuencia+1");
		mysql_query($sql);
	}
	header('Location:index.php');
}
?>
¿Qué significa ese código?
El código quiere decir que se va a insertar dentro de la tabla (nombre de tu tabla) en la columna tags y frecuencia, los valores del input texto, y el número 1 respectivamente. Pero, si ya existe la palabra, entonces que se sume 1 a lo que ya está en frecuencia.

Es bueno que vayas haciéndolo paso por paso e ir probando que todo esté funcionando correctamente, antes de equivocarte y no saber donde.

Hasta ahorita lo que debería funcionar es que tú al insertar por ejemplo 3 palabras separadas por una coma (,) se inserte cada palabra por separado y además la frecuencia sea 1. Y si vuelves a colocar una palabra de esas repetidas, la frecuencia sume y NO se duplique la palabra solo la frecuencia.

Ahora, lo que podría ser más complicado. Mostrar las etiquetas. Para eso yo creo otro archivo aparte y le coloco show.php o mostrar.php


mostrar.php
<?php
require_once('connection/config.php');
$conectar;
$basededatos;
$SLQ_e = sprintf("SELECT * FROM tags GROUP BY tags");
$query_e = mysql_query($SLQ_e);
//Creo un array para meter los datos de las etiquetas
$Etiquetas = array();
while($result_rows = mysql_fetch_object($query_e)){
	//Voy creando el array asociativo
	$Etiquetas[$result_rows->tags]=$result_rows->frecuency;
} 
//defino array con las etiquetas y las apariciones
//pongo un array lleno con datos de prueba, pero habría que generar este array desde base de datos
function tagCloud($Etiquetas){
   //saco los valores máximo y minimo de la apariciones de etiquetas
   $valorMax = max($Etiquetas);
   $valorMin = min($Etiquetas);
   $diferencia = $valorMax - $valorMin;
   //ordeno el array
   ksort($Etiquetas);
   
   foreach ($Etiquetas as $tagName=>$frecuencia){
      //calculo un valor de 0 a 10 para cada etiqueta, porcentualmente según valores máximos y mínimos encontrados
      $valorRelativo = @round((($frecuencia - $valorMin) / $diferencia) * 10);
      //escribo las etiquetas con su estilo dependiendo del valor porcentual
      echo "<span class='etiquetatam$valorRelativo'>";
      echo $tagName;
      echo "</span> ";
   }
   //meto una capa sin float para que tome todo el alto de las etiquetas
   echo "<div style='clear:both'></div>";
   //cierro la nube y las etiquetas
   echo '</div>';
   echo '</div>';
}
tagCloud($Etiquetas);
?>

Es cosa de ponerse a leer, tocar y analizar el código para entender más o menos su función. Luego incluimos el archivo en donde queremos que se vea usando php.
<?php include("mostrar.php"); ?>

Puedes meterlo dentro de un div y darle estilos al div.

Ahora, los estilos CSS para las palabras más repetidas o las menos repetidas.
/* Estilos de fuente para La Tag Cloud */
.etiquetatam0 {
	font-size: 100%;
	color: #777;
	margin-left:10px;
}
.etiquetatam1 {
	font-size: 110%;
	color: #777;
	margin-left:10px;
}
.etiquetatam2 {
	font-size: 120%;   
	color: #707070;
	margin-left:5px;
}
.etiquetatam3 {
	font-size: 130%;   
	color: #666;
	margin-left:5px;
}
.etiquetatam4 {
	font-size: 140%;   
	color: #606060;
	margin-left:5px;
}
.etiquetatam5 {
	font-size: 150%;   
	color: #555;
	margin-left:5px;
}
.etiquetatam6 {
	font-size: 160%;   
	color: #464646;
	margin-left:5px;
}
.etiquetatam7 {
	font-size: 170%;   
	color: #444;
	margin-left:5px;
}
.etiquetatam8 {
	font-size: 180%;   
	color: #373737;
	margin-left:5px;
}
.etiquetatam9 {
	font-size: 190%;   
	color: #333;
	margin-left:5px;
}
.etiquetatam10 {
	font-size: 200%;  
	color: #252525;
	margin-left:10px;
}

Y con eso, tus palabras se verán mejores al estar unas más destacadas que otras.

Bueno espero que les haya servido el aporte, y cualquier cosa no duden para nada en comentarlo que estaré dispuesto a ayudarlos.

Saludos.

20
Puntos
4576
Visitas
15
Resp
Por Jose hace 118 meses
Experto Sitio web
Respuesta #1
Hola Jose, por fin he sacado tiempo para meterme con esto!!, he realizado todo lo que dices pero no muestra nada, como hego para mostrarlo el un div??

Gracias y salu2
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #2
¿Por ejemplo como meto esto en este div?:

<div id="titulo">Nube de etiquetas</div>
<div id="section">

</div>
</div>

Gracias y salu2
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #3
Hola borch, bueno mira el archivo que muestra las tag, en el ejemplo se llama mostrar.php

Para lo que me pides sería
<div id="titulo">Nube de etiquetas</div>
<div id="section">
      <?php include ("/mostrar.php"); ?>
</div>
</div>

Ahora, una pregunta. ¿Se están insertando las etiquetas en la base de datos? Antes de resolver el problema de "mostrar" debes chequear si las etiquetas se están insertando correctamente en la base de datos :P
5
Puntos
Por Jose hace 117 meses
Experto Sitio web
Respuesta #4
si, se insertan las etiquetas bien en la BBDD, pero luego no se me refleja bien en la pagina.

Gacias y salu2
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #5
Hago lo que tu me dices, lo inserto en la página con un include pero no me sale, no coje los estilos, y algo pasa porque los includes que tengo por debajo de este ya no me salen bien. si te mando los archivos ma harias el favor de mirarmelo??

0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #6
Yo creo que el error esta aqui, que no se como solucionar, no se que poner en lo divs, porque los divs los tengo en el mismo documento. El archigo es este:
<?php
require_once('Connections/conexion.php');
$conectar;
$basededatos;
$SLQ_e = sprintf("SELECT * FROM nube GROUP BY tags");
$query_e = mysql_query($SLQ_e);
//Creo un array para meter los datos de las etiquetas
$Etiquetas = array();
while($result_rows = mysql_fetch_object($query_e)){
	//Voy creando el array asociativo
	$Etiquetas[$result_rows->tags]=$result_rows->frecuency;
} 
//defino array con las etiquetas y las apariciones
//pongo un array lleno con datos de prueba, pero habría que generar este array desde base de datos
function tagCloud($Etiquetas){
   //saco los valores máximo y minimo de la apariciones de etiquetas
   $valorMax = max($Etiquetas);
   $valorMin = min($Etiquetas);
   $diferencia = $valorMax - $valorMin;
   //ordeno el array
   ksort($Etiquetas);
   
   foreach ($Etiquetas as $tagName=>$frecuencia){
      //calculo un valor de 0 a 10 para cada etiqueta, porcentualmente según valores máximos y mínimos encontrados
      $valorRelativo = @round((($frecuencia - $valorMin) / $diferencia) * 10);
      //escribo las etiquetas con su estilo dependiendo del valor porcentual
      echo "<span class='etiquetatam$valorRelativo'>";
      echo $tagName;
      echo "</span> ";
   }
   //meto una capa sin float para que tome todo el alto de las etiquetas
   echo "<div style='clear:both'></div>";
   //cierro la nube y las etiquetas
   echo '</div>';
   echo '</div>';
}
tagCloud($Etiquetas);
?>


<div id="titulo">Nube de etiquetas</div>
    <div id="section">
        que pongo aqui???
    </div>
</div>
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #7
Bueno, copia todo lo que está arriba es que PHP y lo metes dentro de la etiqueta section.
<div id="titulo"> Nube de Etiquetas </div>
<dvi id="section">
<?php CODIGO PHP ?>
</div>

De todas maneras, el PHP debería mostrarte las etiquetas, así estén fuera del div.
Mira, veamos..

Yo lo que hacía era cargar mi archivo mostrar.php con AJAX. Pero también puede ser mediante un include como te dije anteriormente solo que debes estar pendiente de esto
<?php require_once(); ?>
Porque si lo tienes 2 veces, te dará error. Por ejemplo yo en el index.php lo tengo así
<?php require_once("connection/config.php"); ?>
Pero en mostrar.php lo tengo así
<?php require_once("../connection/config.php"); ?>
Y tuve que eliminarlo de mostrar.php porque si no me daba el siguiente error:
Fatal error: require_once() [function.require]: Failed opening required '../connection/config.php'



Si quieres comprime el archivo y lo compartes.. Aunque también quisiera ver (una imagen) de como hiciste la tabla en la BBDD. || Primero verifica lo del require_once.

Saludos borch :)

5
Puntos
Por Jose hace 117 meses
Experto Sitio web
Respuesta #8
Hola borch, bueno se supone que los estilos son "mientras más se repite la palabra en la base de datos, más grande y oscura es" Y sobre lo otro. Que no se muetra bien puede por los divs de cierre que están al final.

Creo que si eliminas esto, iría bien.
   //cierro la nube y las etiquetas
   echo '</div>';
   echo '</div>';

No se porque están esas líneas en el código, quizás se quedaron ahí mientras hacía unas pruebas xD A mi no me dan problema estén o no estén. Pero quizás por como tengas tu diseño, a ti sí.



0
Puntos
Por Jose hace 117 meses
Experto Sitio web
Respuesta #9
arreglado!!!,el problema era que tenia una </div> maás, me sobraba, con los nervios se me coló!!!

mil gracias Jose, te debo una
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #10
pregunta, en estos sistemas de nubes de etiquetas, las etiquetas no suelen ser vinculos??
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #11
pero me da un problema, siempre se queda con la clase ".etiquetatam0", tenga la frecuencia que tenga, como puedo arreglar esto??, porque me imagino que según sea la frecuencia mayor será el tamaño, no?
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #12
Hola borch, bueno sí. Las etiquetas suelen ser enlaces que al darles click deberían mostrarte todos los temas con esas etiquetas relacionadas. Nunca había intentado hacer eso, por flojera. Pero ahora que lo planteas me puse a hacerlo. Es fácil porque ya había leído más o menos como hacerlo.

Primero, debes crear otra tabla donde relacionas las otras dos (Temas y Etiquetas) En mi caso yo la llamé tematags y le puse 3 columnas. id, post, tag.

Ésta es la idea.. Cuando tu crees un tema, escribas las etiquetas y al darle click al botón, se hagan 3 consultas de tipo INSERT. Una consulta crea el tema, la otra acumula las etiquetas ordenándolas por frecuencia y la otra consulta inserta el titulo del tema tantas veces como etiquetas tengas.

Por ejemplo si yo creo un tema y le pongo como etiquetas: nuevo,tema

1.- Se crea el tema con su titulo, su contenido y sus etiquetas tal cual como están escritas.
id   titulo    contenido    nuevo,tema

2.- Se insertan las etiquetas por separado en la tabla de tags acumulándose con las que ya existan y sean similares
id    nuevo     1
id    tema       1
3.- Se insertan las etiquetas junto con el titulo del tema en la tabla tematags, ésto para que se pueda mostrar luego.
id    titulo       nuevo
id    titulo       tema

Ok, te mostraré como es mi consulta PHP al insertar un tema.
<?php
	if (isset($_POST["titulo"]) and isset($_POST["contenido"]) and !empty($_POST["titulo"]) and !empty($_POST["contenido"])) {
		$SQL = sprintf("INSERT INTO temas (titulo,seo,autor,contenido,keywords,categoria,fecha) VALUES (%s,%s,%s,%s,%s,%s,%s)", 
						GetSQLValueString($_POST["titulo"], "text"),
						GetSQLValueString(seoURL($_POST["titulo"]), "text"),
						GetSQLValueString($_POST["autor"], "text"),
						GetSQLValueString($_POST["contenido"], "text"),
						GetSQLValueString($_POST["tags"], "text"),
						GetSQLValueString($_POST["categoria"], "int"),
						GetSQLValueString($_POST["fecha"], "text"));
		$query = mysql_query($SQL);
		$etiquetas = explode(",",$_POST["tags"]);
		foreach ($etiquetas as $tag) {
			$SQL_inserTags = sprintf("INSERT INTO tags (tags,frecuency) VALUES (%s, 1) ON DUPLICATE KEY UPDATE frecuency = frecuency+1",
									GetSQLValueString($tag, "text"));
			mysql_query($SQL_inserTags) or die(mysql_error());
			$SQL_inserTemaTags = sprintf("INSERT INTO tematags (post,tag) VALUES (%s, %s)",
									GetSQLValueString($_POST["titulo"], "text"),
									GetSQLValueString($tag, "text"));
			mysql_query($SQL_inserTemaTags) or die(mysql_error());
		}
		header("Location:".$urlWeb);
	}
?>
Bueno ahí se ven las 3 consultas :P

Lueeegoo. Creas un archivo nuevo para mostrar los post que tengan las etiquetas similares. Esto se hace parecido a una Busqueda. Yo llamé al archivo tags.php

Este es mi código PHP, para que te guíes..
<?php
	$request_SQL = sprintf("SELECT * FROM tematags WHERE tag LIKE %s", GetSQLValueString($_GET["tag"], "text"));
	$query = mysql_query($request_SQL, $con);
	while ($request_data_rows = mysql_fetch_array($query)) {
		$SQL_selectPost = sprintf("SELECT * FROM temas WHERE titulo = %s", GetSQLValueString($request_data_rows["post"], "text"));
		$query_selectPost = mysql_query($SQL_selectPost);
		if ($result_rows_post = mysql_fetch_array($query_selectPost)) {
?>

HACES LA ESTRUCTURA DEL POST como por ejemplo..
<div> <?php echo $result_row_post[" "]; ?></div>

<?php } } ?>

Bien, hasta ahora todo debería ir bien. Para hacer que funcione al darle click debes ir a donde creas las tags y colocar el enlace. Suponiendo que la página que muestra los post relacionados a X etiqueta, se llama tags.php Entonces:
 echo "<a href='tags.php?tag".$tagName."'>'";
 echo "<span class='etiquetatam$valorRelativo'>";
 echo $tagName;
 echo "</span> ";
 echo "</a>";

Respecto al problema de la clase y los estilos.. Pues sí, mientras mayor sea la frecuencia, mayor será el tamaño peero todo es relativo. La frecuencia puede ser 100, pero el estilo del máximo tamaño será .etiquetatam10 (Suponiendo que no hay otra etiqueta con frecuencia mayor a 100)..

Así tal cual como está el código a mi me funciona correctamente. No se si editaste alguna variable o algo, si es así verifica que lo hayas hecho bien. Si no, la verdad no se :C
10
Puntos
Por Jose hace 117 meses
Experto Sitio web
Respuesta #13
Ok, gracias Jose, igual lo estoy entendiendo mal, entonces la idea es que cuantas más inserciones tenga la etiqueta, pase de una clase a otra, si tiene una inserción, que la clase de la etiqueta sea ".etiquetatam0", si tiene dos inserciones, que la clase sea ".etiquetatam1", y asi sucesivamente, no??.

Mil gracias por tu ayuda
0
Puntos
Por borch hace 117 meses
Avanzado
Respuesta #14
Si, van variando las clases pero un día pueden ser .etiquetatam7 y dependiendo de las demás etiquetas y sus frecuencias, puede bajar a .etiquetatam3 (un ejemplo). O sea, no es que si metes 3 tags, van a ser .etiquetatam0, .etiquetatam1, .etiquetatam2. No. Las 3 serán .etiquetatam0 Si repites una de ellas, la clase se incrementará.. Y las demás se quedan igual. Si incrementas 2 veces más, otra.. Entonces verás como cambia.
0
Puntos
Por Jose hace 117 meses
Experto Sitio web
Respuesta #15
Pes a mi siempre se me queda con la clase .etiquetatam0, sea la frecuencia que sea, aunque la insertes 10 veces, pero ya investigaré a ver que pasa.

Mil gracias
0
Puntos
Por borch hace 117 meses
Avanzado
Compartir en facebook
Compartir en twitter
Compartir
Para comentar Inicia sesión o Registrate