This will assign font sizes to tags based on their counts. It tries to evenly distribute the font sizes among the tags while keeping all tags with the same counts under the same font size. The data needs to be in the following format:
$tag[tag_name] => Tag Name
$tag[tag_count] => Number of instances of this tag
$tag[tag_class] => Resulting class name, ex: tag1, tag2
Please note that this does not work with a class object. This was designed to work with an array only.
Once you create an array of these objects, you can feed them to the cloud_tags() function which will assign each $tag with a tag_class based on it's tag_count and the overall number of font sizes and tags. The return result is the array sorted aphabetically with each tag_class properly assigned.
You may change the $tag_sizes variable to indicate fewer or more font sizes. You can create your css classes in the format tag1, tag2, tag3, etc. or use the CSS found in the screenshot: Tagcloud CSS Stylesheet
$tags = cloud_tags($tags);
/****************************************************************************************/
// Sorts a list of tags by their count ascending.
function tag_asort($tag1, $tag2)
{
if($tag1[tag_count] == $tag2[tag_count])
{
return 0;
}
return ($tag1[tag_count] < $tag2[tag_count]) ? -1 : 1;
}
/****************************************************************************************/
// Sorts a list of tags alphabetically by tag_name
function tag_alphasort($tag1, $tag2)
{
if($tag1[tag_name] == $tag2[tag_name])
{
return 0;
}
return ($tag1[tag_name] < $tag2[tag_name]) ? -1 : 1;
}
/****************************************************************************************/
// Assigns classes to each given tag.
function cloud_tags($tags)
{
$tag_sizes = 7;
usort($tags, "tag_asort");
if(count($tags) > 0)
{
// Start with the sorted list of tags and divide by the number of font sizes (buckets).
// Then proceed to put an even number of tags into each bucket. The only restriction is
// that tags of the same count can't span 2 buckets, so some buckets may have more tags
// than others. Because of this, the sorted list of remaining tags is divided by the
// remaining 'buckets' to evenly distribute the remainder of the tags and to fill as
// many 'buckets' as possible up to the largest font size.
$total_tags = count($tags);
$min_tags = $total_tags / $tag_sizes;
$bucket_count = 1;
$bucket_items = 0;
$tags_set = 0;
foreach($tags as $key => $tag)
{
$tag_count = $tag[tag_count];
// If we've met the minimum number of tags for this class and the current tag
// does not equal the last tag, we can proceed to the next class.
if(($bucket_items >= $min_tags) and $last_count != $tag_count and $bucket_count < $tag_sizes)
{
$bucket_count++;
$bucket_items = 0;
// Calculate a new minimum number of tags for the remaining classes.
$remaining_tags = $total_tags - $tags_set;
$min_tags = $remaining_tags / $bucket_count;
}
// Set the tag to the current class.
$tags[$key][tag_class] = 'tag'.$bucket_count;
$bucket_items++;
$tags_set++;
$last_count = $tag_count;
}
usort($tags, 'tag_alphasort');
}
return $tags;
}
how to use the cloud_tag class (see post below for class source):
// create some fake input
$tags = array();
$tempTag[tag_name] = \'ajax\';
$tempTag[tag_count] = 3;
$tags[] = $tempTag;
$tempTag[tag_name] = \'mysql\';
$tempTag[tag_count] = 3;
$tags[] = $tempTag;
$tempTag[tag_name] = \'linux\';
$tempTag[tag_count] = 1;
$tags[] = $tempTag;
$tempTag[tag_name] = \'php\';
$tempTag[tag_count] = 6;
$tags[] = $tempTag;
// instantiate a cloud
$cloud = new cloud_tag();
// the class already has defaults, but let\'s override them for fun
$cloud->set_label(\'cloud\'); // css classes will be cloud1, cloud2, etc.
$cloud->set_tagsizes(7); // 7 font sizes will be used
$newtags = $cloud->make_cloud($tags); // make a tag cloud
Great snippet. I created a class around it to make management easier and to let you set the number of buckets (fonts) and the base css class name. How to use in the next post.
class cloud_tag
{
// constructor. init our variables
function cloud_tag()
{
$this->tag_label = \"tag\";
$this->tag_sizes = 7;
}
// set the label for the css class
function set_label($label) {$this->tag_label = $label;}
// set the number of buckets
function set_tagsizes($sizes) {$this->tag_sizes = $sizes;}
// create a cloud tag
function make_cloud($tags)
{
usort($tags, array($this,\'tag_asort\'));
if(count($tags) == 0) return $tags;
// Start with the sorted list of tags and divide by the number of font sizes (buckets).
// Then proceed to put an even number of tags into each bucket. The only restriction is
// that tags of the same count can\'t span 2 buckets, so some buckets may have more tags
// than others. Because of this, the sorted list of remaining tags is divided by the
// remaining \'buckets\' to evenly distribute the remainder of the tags and to fill as
// many \'buckets\' as possible up to the largest font size.
$total_tags = count($tags);
$min_tags = $total_tags / $this->tag_sizes;
$bucket_count = 1;
$bucket_items = 0;
$tags_set = 0;
foreach($tags as $key => $tag)
{
$tag_count = $tag[tag_count];
// If we\'ve met the minimum number of tags for this class and the current tag
// does not equal the last tag, we can proceed to the next class.
if(($bucket_items >= $min_tags) and $last_count != $tag_count and $bucket_count < $this->tag_sizes)
{
$bucket_count++;
$bucket_items = 0;
// Calculate a new minimum number of tags for the remaining classes.
$remaining_tags = $total_tags - $tags_set;
$min_tags = $remaining_tags / $bucket_count;
}
// Set the tag to the current class.
$tags[$key][tag_class] = $this->tag_label.$bucket_count;
$bucket_items++;
$tags_set++;
$last_count = $tag_count;
}
usort($tags, array($this,\'tag_alphasort\'));
return $tags;
}
/*-------------------------------------------------------
internal-use-only below here
-------------------------------------------------------*/
// sorts a list of tags by their count ascending.
function tag_asort($tag1, $tag2)
{
if($tag1[tag_count] == $tag2[tag_count]) return 0;
return ($tag1[tag_count] < $tag2[tag_count]) ? -1 : 1;
}
// sorts a list of tags alphabetically by tag_name
function tag_alphasort($tag1, $tag2)
{
if($tag1[tag_name] == $tag2[tag_name]) return 0;
return ($tag1[tag_name] < $tag2[tag_name]) ? -1 : 1;
}
/*-------------------------------------------------------
member variables
-------------------------------------------------------*/
var $tag_label; // the css base class name
var $tag_sizes; // number of buckets (font sizes)
}
Pomppu, could you please help us how to implement this on my site. Sorry I cannot provide the URL to my site as it is on a test bed internally behind the firewall.
I got machine setup with fedora core 4 running apache, mysql, perl, and php.
I am not a php programmer myself and i know little bit about CGI scripting. Your help will be much appreciated.
This should do the trick here:
require(\"databaseconnection.php\");
$tags=array();
$sql = \"SELECT tag, COUNT(tag) as count FROM links_tags GROUP BY tag ORDER BY count\";
$result = mysql_query($sql);
while ($rowInfo = mysql_fetch_assoc($result))
{
$tempTag[tag_name] = $rowInfo[\'tag\'];
$tempTag[tag_count] = $rowInfo[\'count\'];
$tags[] = $tempTag;
}
$tags = cloud_tags($tags);
I\'ve been banging my head onto a wall while trying to get this to work. I cannot provide a working sample code, but here\'s a try so if anyone can tell me what\'s wrong with my attempt, then there\'s the sample for you too, an_goodboy2000.
My problem is that there is something wrong with the array of objects I\'m creating. I get an error message for each tag object in my array saying: \"Warning: Cannot use a scalar value as an array in /home/[removed]/links.php on line 103\"
The line 103 looks like this: $tags[$key][tag_class] = \'tag\'.$bucket_count;
This is my code:
require(\"databaseconnection.php\");
class tag {
var $tag_name;
var $tag_count;
var $tag_class;
}
$tags=array();
$sql = \"SELECT tag, COUNT(tag) as count FROM links_tags GROUP BY tag ORDER BY count\";
$result = mysql_query($sql);
while ($rowInfo = mysql_fetch_assoc($result))
{
$tempTag=new tag();
$tempTag->tag_name = ($rowInfo[\'tag\']);
$tempTag->tag_count = ($rowInfo[\'count\']);
$tags[]=$tempTag;
}
cloud_tags($tags);
Could someone please show me what I\'m doing wrong. Best regards and thanks in advance.