Tag Cloud Script (Version 2) is now Available, with more customizable features
Introduction
In this tutorial i am going to show you how to create a basic word / tag cloud using php and utilizing php classes for easy inclusion. I am going to create a class based cloud, this is because it will be more convenient for you to adapt it on your own website(s), if you don't know much about class based programming then click here to take a look at the class tutorial.
Tutorial
First we need to create the class and for this example i am going to call the class "wordCloud" this is just my personal naming preference, feel free to call your cloud whatever you like, we are also going to assign the first class variable which will be the container of all the items in the array, we will call it "wordsArray".
<?
class wordcloud
{
var $wordsArray = array();
}
?>
Next, we need to assign the first function, because of the difference between PHP 4 and PHP 5 Constructors, i have created a method (function) called "wordCloud" and "__construct", when wordCloud is called it simultaneously call the PHP 5 constructor, so it's compatible with both versions like so.
<?
function __construct($words = false)
{
if ($words !== false && is_array($words))
{
foreach ($words as $key => $value)
{
$this->addWord($value);
}
}
}
function wordCloud($words = false)
{
$this->__construct($words);
}
?>
The main constructor basically can be used to load the words when the class object is created.
Now, we need to create a function to add words into the array as and when we need them.
<?
function addWord($word, $value = 1)
{
$word = strtolower($word);
if (array_key_exists($word, $this->wordsArray))
$this->wordsArray[$word] += $value;
else
$this->wordsArray[$word] = $value;
return $this->wordsArray[$word];
}
?>
The method above will basically check the array of words and if the word exists it will increase the repetition value, this can also be adjusted by manual input.
Next, we need to be able to get the size of the array, now because we have an array with values, we can use the values of all the items in the array added together like so.
<?
function getCloudSize()
{
return array_sum($this->wordsArray);
}
?>
Next, we need to create a function to calculate the class / range that each specific word should be assigned to, this will be done by using the percentage that will be returned from the final function.
<?
function getClassFromPercent($percent)
{
if ($percent >= 99)
$class = 1;
else if ($percent >= 70)
$class = 2;
else if ($percent >= 60)
$class = 3;
else if ($percent >= 50)
$class = 4;
else if ($percent >= 40)
$class = 5;
else if ($percent >= 30)
$class = 6;
else if ($percent >= 20)
$class = 7;
else if ($percent >= 10)
$class = 8;
else if ($percent >= 5)
$class = 9;
else
$class = 0;
return $class;
}
?>
Next we create a function that will shuffle all the values in the cloud, this is so that we can have a different output each time, this could be adapted so that it only shuffles the cloud if choose to.
<?
function shuffleCloud()
{
$keys = array_keys($this->wordsArray);
shuffle($keys);
if (count($keys) && is_array($keys))
{
$tmpArray = $this->wordsArray;
$this->wordsArray = array();
foreach ($keys as $key => $value)
$this->wordsArray[$value] = $tmpArray[$value];
}
}
?>
Now, we need to create a function to display the words, i have decided to make this function have two possible outputs, this is because if you would like more control over the output or if you would like to use less standard class names then you can do so, the two possible output types are an php array and html spans.
function showCloud($returnType = "html")
{
$this->shuffleCloud();
$this->fullCloudSize = $this->getCloudSize();
$this->max = max($this->wordsArray);
if (is_array($this->wordsArray))
{
$return = ($returnType == "html" ? "" : ($returnType == "array" ? array() : ""));
foreach ($this->wordsArray as $word => $popularity)
{
$sizeRange = $this->getClassFromPercent(($popularity / $this->max) * 100);
if ($returnType == "array")
{
$return[$word]['word'] = $word;
$return[$word]['sizeRange'] = $sizeRange;
if ($currentColour)
$return[$word]['randomColour'] = $currentColour;
}
else if ($returnType == "html")
{
$return .= "<span class='word size{$sizeRange}'> {$word} </span>";
}
}
return $return;
}
}
Ok, so now we have the class, we need to use this to create our cloud, this could be done like so.
<?
// You could add items to the class by passing them through the constructor
$randomWords = array("webmasterworld", "Computer", "Skateboarding", "PC", "music", "music", "music", "music", "PHP", "C", "XHTML", "programming", "forums", "Chill out", "email", "forums", "Computer", "GTA", "Freetimers", "css", "mysql", "sql", "css", "mysql", "sql", "forums", "internet", "class", "object", "method", "music", "music", "music", "music", "gui", "encryption");
$cloud = new wordCloud($randomWords);
// Or you could assign them manually
$cloud->addWord("harvey", 5);
$cloud->addWord("music", 12);
echo $cloud->showCloud();
?>
Don't forget to create your styles to display the different size fonts, this is a little something i have come up with.
<style>
<!--
.word {
font-family: Tahoma;
padding: 4px 4px 4px 4px;
letter-spacing: 3px;
}
span.size1 {
color: #000;
font-size: 2.4em;
}
span.size2 {
color: #333;
font-size:2.2em;
}
span.size3 {
color: #666;
font-size: 2.0em;
}
span.size4 {
color: #999;
font-size: 1.0em;
}
span.size5 {
color: #aaa;
font-size: 1.6em;
}
span.size6 {
color: #bbb;
font-size: 1.4em;
}
span.size7 {
color: #ccc;
font-size: 1.2em;
}
span.size8 {
color: #ddd;
font-size: .8em;
}
//-->
</style>
To finish off i will finish with the code in full.
Full PHP Tag Cloud Class
<?
/*
@wordCloud
Author: Derek Harvey
Website: www.lotsofcode.com
@Description
PHP Tag Cloud Class, a nice and simple way to create a php tag cloud, a database and non-database solution.
*/
class wordCloud
{
var $wordsArray = array();
/*
* PHP 5 Constructor
*
* @param array $words
* @return void
*/
function __construct($words = false)
{
if ($words !== false && is_array($words))
{
foreach ($words as $key => $value)
{
$this->addWord($value);
}
}
}
/*
* PHP 4 Constructor
*
* @param array $words
* @return void
*/
function wordCloud($words = false)
{
$this->__construct($words);
}
/*
* Assign word to array
*
* @param string $word
* @return string
*/
function addWord($word, $value = 1)
{
$word = strtolower($word);
if (array_key_exists($word, $this->wordsArray))
$this->wordsArray[$word] += $value;
else
$this->wordsArray[$word] = $value;
return $this->wordsArray[$word];
}
/*
* Shuffle associated names in array
*/
function shuffleCloud()
{
$keys = array_keys($this->wordsArray);
shuffle($keys);
if (count($keys) && is_array($keys))
{
$tmpArray = $this->wordsArray;
$this->wordsArray = array();
foreach ($keys as $key => $value)
$this->wordsArray[$value] = $tmpArray[$value];
}
}
/*
* Calculate size of words array
*/
function getCloudSize()
{
return array_sum($this->wordsArray);
}
/*
* Get the class range using a percentage
*
* @returns int $class
*/
function getClassFromPercent($percent)
{
if ($percent >= 99)
$class = 1;
else if ($percent >= 70)
$class = 2;
else if ($percent >= 60)
$class = 3;
else if ($percent >= 50)
$class = 4;
else if ($percent >= 40)
$class = 5;
else if ($percent >= 30)
$class = 6;
else if ($percent >= 20)
$class = 7;
else if ($percent >= 10)
$class = 8;
else if ($percent >= 5)
$class = 9;
else
$class = 0;
return $class;
}
/*
* Create the HTML code for each word and apply font size.
*
* @returns string $spans
*/
function showCloud($returnType = "html")
{
$this->shuffleCloud();
$this->max = max($this->wordsArray);
if (is_array($this->wordsArray))
{
$return = ($returnType == "html" ? "" : ($returnType == "array" ? array() : ""));
foreach ($this->wordsArray as $word => $popularity)
{
$sizeRange = $this->getClassFromPercent(($popularity / $this->max) * 100);
if ($returnType == "array")
{
$return[$word]['word'] = $word;
$return[$word]['sizeRange'] = $sizeRange;
if ($currentColour)
$return[$word]['randomColour'] = $currentColour;
}
else if ($returnType == "html")
{
$return .= "<span class='word size{$sizeRange}'> {$word} </span>";
}
}
return $return;
}
}
}
?>
<style>
<!--
.word {
font-family: Tahoma;
padding: 4px 4px 4px 4px;
letter-spacing: 3px;
}
span.size1 {
color: #000;
font-size: 2.4em;
}
span.size2 {
color: #333;
font-size:2.2em;
}
span.size3 {
color: #666;
font-size: 2.0em;
}
span.size4 {
color: #999;
font-size: 1.0em;
}
span.size5 {
color: #aaa;
font-size: 1.6em;
}
span.size6 {
color: #bbb;
font-size: 1.4em;
}
span.size7 {
color: #ccc;
font-size: 1.2em;
}
span.size8 {
color: #ddd;
font-size: .8em;
}
span.size0 {
color: #ccc;
font-size: .6em;
}
//-->
</style>
<?
$randomWords = array(
"webmasterworld", "Computer", "Skateboarding", "PC", "music", "music", "music", "music", "PHP", "C", "XHTML", "eminem", "programming", "forums", "webmasterworld",
"Chill out", "email", "forums", "Computer", "GTA", "css", "mysql", "sql", "css", "mysql", "sql",
"forums", "internet", "class", "object", "method", "music", "music", "music", "music", "gui", "encryption"
);
$cloud = new wordCloud($randomWords);
$cloud->addWord("music", 12);
$cloud->addWord("downloads", 8);
$cloud->addWord("internet", 17);
$cloud->addWord("PHP", 22);
$cloud->addWord("CSS", 32);
echo $cloud->showCloud();
?>
And this is how it should look, i have changes some of the colours for the more important words.
How to intergrate with a MySQL database.
Depending on how your information is stored in your database, an individual field or a comma seperated field then you can place the tags into the cloud from a MySQL results like follows.
Let's say we have a table called tags, if we have comma seperated values.
<?php
$cloud = new wordcloud();
$getBooks = mysql_query("SELECT title FROM `tags`");
if ($getBooks)
{
while ($rowBooks = mysql_fetch_assoc($getBooks))
{
$getTags = explode(' ', $rowBooks['title']);
foreach ($getTags as $key => $value)
{
$value = trim($value);
$cloud->addWord($value);
}
}
}
$myCloud = $cloud->showCloud('array');
if (is_array($myCloud))
{
foreach ($myCloud as $key => $value)
{
echo ' <a href="path/to/tags/'.$value['word'].'" style="font-size: 1.'.$value['sizeRange'].'em">'.$value['word'].'</a> ';
}
?>
If the tag is an individual field, then:
<?php
$cloud = new wordcloud();
$getBooks = mysql_query("SELECT title FROM `tags`");
if ($getBooks)
{
while ($rowBooks = mysql_fetch_assoc($getBooks))
{
$cloud->addWord($rowBooks['title']);
}
}
}
$myCloud = $cloud->showCloud('array');
if (is_array($myCloud))
{
foreach ($myCloud as $key => $value)
{
echo ' <a href="tags_url/'.urlencode($value['word']).'" style="font-size: 1.'.($value['range']).'em">'.$value['word'].'</a> ';
}
?>
Video Tutorials
Finished.
Ok, so that's the tutorial over. Please have fun with the code, if you are a little confused then please check out the video tutorials, the quality is a little bad at the moment but i hope to arrange some better videos soon!
All comments and questions are welcome, provided they are related to this page.