[TUTO] Simple Smart TagCloud with PHP

Status
Not open for further replies.

jokerhacker

Active Member
415
2010
45
0
Hi all,

Tag clouds are widely used on all kind of website, specially search tags.
So, basically the website will log search terms and then call them to build the tag cloud.
As we need such system to be smart and lightweight, we are going to use XML files because we hate DB systems :P

1st function: Storing search terms
Your website has (of course) a page where people can search contents on it.
Its name is something like "search.php" or something. Basically, we need to cut search string into tags, we can do that with explode(), so

$srch_str
, will contain the search string (assuming it's well filtered and validated, if you want me to explain how to do so, just mention iit in a reply)
PHP:
$tags = explode(" ", $srch_str);
We now have all the terms in the search string arranged in an array! :D
After that, we need to store it, we need sonmething quick and efficient, a simple txt file would be enough. Let's say the filename is "tempsearch.txt"

(i'll explain later why i added temp).
PHP:
$handle = fopen( getcwd() . "/tempsearch.txt", "a");
foreach ( $tags as $tag )
     fwrite($handle, $tag . PHP_EOL);
fclose($handle);
What is that "a"?
It's the type of access we require to the file, a means
Open for writing only; place the file pointer at the end of the file. If the file does not

exist, attempt to create it.
What is that "PHP_EOL"?
Since every platform has its own caracters, we need to make many if statements to determine wich one we need to do line break (like \n or \n\r)
PHP_EOL is The correct 'End Of Line' symbol for this platform. Available since PHP 4.3.10 and PHP 5.0.2

we said we need it to be efficient and quick, that txt file is quick for execution so it won't slow down page execution time for visitiors, but we need it to

be efficient too! Thats why we need to transfer tags from it to a better format: it's XML, buddy!
Our XML file will be growing and act as a DB. Let's call it "tagindex.xml".
We are going to create a small function to transfer tags from "tempsearch.txt" to "tagindex.xml" to be usable.
Let's do it!
We create our empty xml file
Code:
<?xml version="1.0"?>
<tags></tags>

Now PHP!
PHP:
$tagdb = simplexml_load_file("tagindex.xml"); // assuming it does already exists!
$handle = fopen( getcwd() . "/tempsearch.txt", "r+");
if ($handle) {
    while (($tag = fgets($handle, 1024)) !== false) {
        $tagdb->addChild($tag);
}
fclose($handle);
$tagdb->asXML("tagindex.xml");
}

Our XML file is updated now, when we want to show the tag cloud we will use that XML file not txt one.
You can set this code to run each 15mins, less or more depending on your server capacity.

2nd function: Showtime!
We all know that terms in tagclouds are not equal, each element has its own font size depending on its "frequency", let's say our minimal font size

is 10, and max 40.
First of all we pickup randomly n different tags to display.
PHP:
$tagdb = simplexml_load_file("tagindex.xml");
$n = 20; //beware n must be greater than the number of unique tags in tagdb!
//for execution time we will require n to not to be greater than 1/2 of unique tags
$half = sizeof((array)$tagdb) * 0.5;
if($half < $n) 
     $n = sizeof((array)$tagdb); 
$tags = array();
while( sizeof($tags) < $n ){
     $rand_tag = array_rand((array)$tagdb);
     if (!in_array($rand_tag, $tags)
          $tags[] = $rand_tag;
}

Now for each tag we need a score, that's its frequenccy.
PHP:
$scores = array();
foreach($tags as $tag) 
     scores[] = sizeof($tagdb->$tag);
We need Some Maths to determine what font size we are going to use for each tag
PHP:
$min = min($scores);
$max = max($scores);
//some maths :)
$coef = (40 - 10)/($max - $min);
$suf = 40 - $coef * $max;
Here is how we are going to show the output
PHP:
echo '<div id="tagcloud" class="tagcloud">
<ul>
';
foreach ( $tags as $i => $tag ) {
	$size = round($coef * $scores[$i] + $suf);
	echo '<li style="font-size:' . $size . 'px;">' . $tag . '</li>';
}
echo '</ul></div>';
Hurray! Thats all we need to build our very own TagCloud system. It's quick, efficient and smart!
you can integrate it in any website which has a search bar.

Now let's organize our work, we'll create pages and include then to not to get nested code.

search_include.php
PHP:
$tags = explode(" ", $srch_str);
$handle = fopen( getcwd() . "/tempsearch.txt", "a");
foreach ( $tags as $tag )
     fwrite($handle, $tag . PHP_EOL);
fclose($handle);
Now you have add this line to your search page
PHP:
include ('search_include.php');
Our empty xml file
Code:
<?xml version="1.0"?>
<tags></tags>
tag_cronjob.php
PHP:
$tagdb = simplexml_load_file("tagindex.xml"); // assuming it does already exists!
$handle = fopen( getcwd() . "/tempsearch.txt", "r+");
if ($handle) {
    while (($tag = fgets($handle, 1024)) !== false) {
        $tagdb->addChild($tag);
}
fclose($handle);
$tagdb->asXML("tagindex.xml");
//empty tempsearch.txt
file_put_contents('tempsearch.txt', '');
}
showtags.php
PHP:
$tagdb = simplexml_load_file("tagindex.xml"); 
$n = 20; //beware n must be greater than the number of unique tags in tagdb! 
//for execution time we will require n to not to be greater than 1/2 of unique tags 
$half = sizeof((array)$tagdb) * 0.5;
if($half < $n) 
     $n = sizeof((array)$tagdb); 
$tags = array(); 
while( sizeof($tags) < $n ){ 
     $rand_tag = array_rand((array)$tagdb); 
     if (!in_array($rand_tag, $tags)) 
          $tags[] = $rand_tag; 
} 
$scores = array(); 
foreach($tags as $tag)  
     $scores[] = sizeof($tagdb->$tag); 
$min = min($scores); 
$max = max($scores); 
//some maths :) 
$coef = (40 - 10)/($max - $min); 
$suf = 40 - $coef * $max; 
//output 
echo '<div id="tagcloud" class="tagcloud"> 
<ul> 
'; 
foreach ( $tags as $i => $tag ) { 
    $size = round($coef * $scores[$i] + $suf); 
    echo '<li style="font-size:' . $size . 'px;">' . $tag . '</li>'; 
} 
echo '</ul></div>';

Now you include showtags.php wherever you want that tagcloud to be displayed. just put this
PHP:
include ('showtags.php');
You also need some CSS to format your tag cloud, because it's ugly if you display it as a normal list on your home page :o

Example of quick css styling
Code:
padding:10px;
display: inline;

2Pnpy3.png


Well this is my first tutorial, i hope you all like it. I'll be glad to see your comments, reviews and code improvements.
All of the above code is tested and is working correctly, however, please test and give feedback ;)

Thanks for reading :)
 
Last edited:
4 comments
Status
Not open for further replies.
Back
Top