Tag Cloud

By tompouce bezehon (tompouce)
Here's a nice way to do a simple and customizable tag cloud.
First add a tag column to your table.
Add keywords separated by commas.

Here's the component: (nuage.php)

Component Class:

Download code <?php 
<?php
class NuageComponent extends Object
{
    var 
$controller true;
    
    function 
startup(&$controller)
    {
        
$this->controller = &$controller;
        
$Articlez = new Article//Model name
        
$data $Articlez->query("SELECT article_tags AS tag FROM articles"); //Select only the tags column.
        
$this->controller->set('Tagz',$data);
    }
}
?>
?>

And here's the element: (nuage.thtml)

View Template:

Download code
<?php
        $mots 
= array();
        foreach (
$Tagz as $_tag) {
            
            
$tag $_tag['articles']['tag'];
            if (
$tag):
            if (
stristr($tagchr(44))) {
                
                
$tags explode(chr(44), $tag);
                
                foreach(
$tags as $__tag):
                    if(
array_key_exists($__tag$mots)) $mots[$__tag]++;
                    else 
$mots[$__tag] = '1';
                endforeach;
            }

            else {
                if(
array_key_exists($tag$mots)) $mots[$tag]++; 
                else 
$mots[$tag] = '1';
            }
        
        endif;
            
        }
        
    
$max_size 25$max_weight 900//max font size and max font weight
    
$min_size 5$min_weight 100//min font size and min font weight
    
$max_qty max(array_values($mots)); //the maximum data
    
$min_qty min(array_values($mots)); //the minimum data
    
        
$spread $max_qty $min_qty;
        if (
== $spread) { 
            
$spread 1;
        }

        
$step = ($max_size $min_size)/($spread);
        
$bold = ($max_weight $min_weight)/($spread);

        foreach (
$mots as $key => $value) {

            
$size round($min_size + (($value $min_qty) * $step),0);
            
$weight round($min_weight + (($value $min_qty) * $bold),0);
            
            echo 
'<a href="/articles/tags/'.$key.'" style="font-weight: '.$weight.'; font-size: '.$size.'pt" title="'.$value.' articles avec le tag '.$key.'">'.$key.'</a> ';
        }
?>

Do whatever you want with it and give me your comments.

Hope you like this!

 

Comments 89

CakePHP Team Comments Author Comments
 

Comment

1 Great tutorial

Great idea
Posted Oct 9, 2006 by Stanislav N. Yakubenko
 

Comment

2 Aligning of tags

Because the tags are sometimes very different in size, it makes sense to include another style with every tag:

echo ''.$key.' ';

Just include in the "style" the "vertical-align: middle;" and everything tag is aligned around a vertical line.
Posted Oct 18, 2006 by Siegfried Hirsch
 

Question

3 Question

How can you get all articles related with one tag?

Like http://www.misite.com/articles/tags/php
I did like "SELECT * from news WHERE tags LIKE '%php%'; but this will return all like php , phpnuke, cakephp.

Thanks
Posted Dec 31, 1969 by Fabian Ramirez
 

Comment

4 Query String

Having a query string directly in the Component is probably not the best way to do this. It should be the model that sends you the data you need.

But overall the article does have a good element for tag cloud and is definitely useful. I will give this a try.
Posted Jun 26, 2007 by Ketan
 

Comment

5 Poor adherence to MVC architecture or Cake goals

From the cake manual:

[url=http://manual.cakephp.org/chapter/components]http://manual.cakephp.org/chapter/components
A component gets access to the controller that loaded it through the startup() method shown above. This method is called immediately after Controller::beforeFilter(). This allows you to set component properties in the beforeFilter method, which the component can act on in it’s startup() method.

Because CakePHP loads models in a lazy fashion, it's usually not a good idea to create model instances in components. If you need model data in a component, it's best to pass that data in through one of the component's methods:


<?php

class UsersController extends AppController
{
    var 
$uses = array('Apple');
    var 
$components = array('Foo');

    function 
index()
    {
        
$data $this->Foo->doFoo($this->Apple->findAll());
    }
}

?>
Posted Nov 5, 2007 by Raphael Spindell
 

Comment

6 You can do it in the database side

How can you get all articles related with one tag?

Like http://www.misite.com/articles/tags/php
I did like "SELECT * from news WHERE tags LIKE '%php%'; but this will return all like php , phpnuke, cakephp.

Thanks

You can put something like this:
When you have you tag word in the link you can search in the database as the following way.

select tags from templates
where tags like '%,green'
UNION
select tags from templates
where tags like '%,green,'
UNION
select tags from templates
where tags like '%green,'
UNION
select tags from templates
where tags ='green';

Regards,
Lucks
Posted Mar 28, 2008 by Luis de Jesus Lopez Hernandez