Cake Meet Pie

by rloaderro
A Helper class that integrates EQ Smooth Pie Graph with your Cake application. EQ Smooth Pie Graph generates pie charts with smooth edges, looks great, and it's free - read on.

For a Cake application that needed the ability to generate pie charts I investigated many of the available classes for PHP. Ultimately I choose EQ Smooth Pie Graph because it works with PHP 4/5, looks great and it's free! Don't take my word for it - here is a clip from a screen shot of my EQ Smooth Pie Graph implementation:


http://www.electricprism.com/aeron/eq_pie.gif

To integrate EQ Smooth Pie Graph with your Cake application follow these steps:


1. Download EQ Smooth Pie Graph from phpclasses.org!


The EQ Smooth Pie Graph class is provided free for non-commercial use by the author Elibert Johan (which I interpret as just don't try to sell his class!). Here is a direct link http://phpclasses.ca/browse/package/2498.html from a Mirror site. The file you are interested in is called "class_eq_pie.php" and must be placed in the "vendors" folder of your Cake application.


Note: In order to function as I needed, I had to comment out line 172 of the class.



// header('Content-type: image/png');

2. Prepare the Data for your Pie Chart!


The eq_pie class requires data to be a nested array with the following structure: array("title str", value_int, "#hex_color_str")


Personally, I prefered to prepare the data in a controller before passing it to the view. An example of my controller code could be:



$eq_data = array();

$eq_data[] = array('English', 10, '#E5E5E5');
$eq_data[] = array('Spanish', 5, '#C1D0D6');

$this->set('eq_data', $eq_data);

3. Initialize the Pie Chart Helper!


Copy the following Helper class and paste it into a file named "pie_chart.php" in the "view/helpers" folder of your Cake application.


Helper Class:

<?php 
/**
 * Pie Chart Helper
 *
 * @version 1.0
 * @author Aeron Glemann <http://www.electricprism.com/aeron>
 * @license MIT Style License
 */

class PieChartHelper extends Helper {
    var 
$helpers = array('Html');
    
    var 
$total 0;
    
    var 
$data null;
    
    var 
$path '';
    
    var 
$eq_pie null;

    
/**
     * Create eq_pie class instance
     *
     * @param array $data Data for pie chart
     * @return bool Successful
     */

    
function create($data = array()) {
        if (empty(
$data)) {
            return 
false;
        }

        foreach(
$data as $eq_data) {
            
$this->total += $eq_data[1];   
        }

        if (
$this->total == 0) {
            return 
false;  
        }

        
$this->data $data;  

        
$this->path WWW_ROOT.'img'.DS.'eq_pie';

        if (!
is_dir($this->path)) {            
            
mkdir($this->path0777);  
            
            if (!
is_dir($this->path)) {  
                
debug("Error, Unable to create folder at $this->path (check permissions).");
                return 
false;            
            }
        }    

        
vendor('class_eq_pie');

        
$this->eq_pie = new eq_pie;  

        return 
true;   
    }


    
/**
     * Draw a pie chart
     *
     * @param int $width Width of pie chart graphic in pixels
     * @param int $height Height of pie chart graphic in pixels (controls perspective, does not include $shadow)
     * @param int $shadow How "tall" the pie chart is
     * @param string $backgroundColor Background color as hexidecimal
     * @param bool $legend Draw legend too?
     * @return string HTML image
     */

    
function draw($width 100$height 100$shadow 10$backgroundColor '#ffffff'$legend 1) {
        
$hash md5($this->_implode_r(array($this->data$width$height$shadow$backgroundColor$legend)));

        
$alt = array();

        foreach(
$this->data as $eq_data) {
            
$alt[] = $eq_data[0].' '.number_format($eq_data[1] / $this->total 1001).'%';
        }

        
$alt join(', '$alt);    

        
$filename $this->path.DS.$hash.'.png';

        if (
is_readable($filename)) {
            list(
$w$h) = getimagesize($filename); 

            return 
$this->Html->image(('eq_pie'.DS.$hash.'.png'), array('alt' => $alt'width' => $w'height' => $h));
        }

        
$this->eq_pie->MakePie($filename$width$height$shadow$backgroundColor$this->data$legend); 

        list(
$w$h) = getimagesize($filename); 

        return 
$this->Html->image(('eq_pie'.DS.$hash.'.png'), array('width' => $w'height' => $h));
    }


    
/**
     * Create an HTML legend
     *
     * @param string $class Name of CSS class to apply to legend div
     * @return string HTML div and unordered list 
     */

    
function legend($class 'legend') {
        
$out = array();
        
$out[] = "<div class='$class'>";
        
$out[] = "<ul>";

        foreach(
$this->data as $eq_data) {
            
$hash md5($eq_data[2]);

            
$filename $this->path.DS.$hash.'.png';

            if (!
is_readable($filename)) {                        
                
$img = @imagecreatetruecolor(11);
                
$r hexdec(substr($eq_data[2],1,2));
                
$g hexdec(substr($eq_data[2],3,2));
                
$b hexdec(substr($eq_data[2],5,2));                 

                
imagefill($img00imagecolorallocate($img$r$g$b));

                
imagepng($img$filename);
                
imagedestroy($img);
            }

            
$image $this->Html->image(('eq_pie'.DS.$hash.'.png'), array('alt' => $eq_data[2]));

            
$out[] = sprintf("<li>$image %s</li>"$eq_data[0].' <span>'.number_format($eq_data[1] / $this->total 1001).'%</span>'); 
        }

        
$out[] = "</ul>";
        
$out[] = "</div>";

        return 
join("\n"$out);
    }


    
/**
     * Convenience function to merge multi-dimensional array as string
     *
     * @param array $pieces Multi-dimensional array to merge
     * @return string Merged array
     */

    
function _implode_r($pieces) {
        
$out "";

        foreach (
$pieces as $piece) {
            if (
is_array($piece)) $out .= $this->_implode_r($piece);
            else 
$out .= $piece;
        }

        return 
$out;
    } 
}
?>

The Helper is initialized with the "create" function. An example would be (using the data from step 2):



<?php if ($pieChart->create($eq_data)) {
    
// drawing code goes here
?>

The Helper requires write permission (chmod +w) to the "webroot/img" folder in order to function correctly. It will return an error if that is not the case.


4. Draw a Pie Chart!


Once the Helper has been initialized you can draw as many charts as you need with the "draw" function. A complete example would be:



<?php if ($pieChart->create($eq_data)) {
    echo 
$pieChart->draw(18010020); 
?>

The parameters used above are 180px for the image width, 100px for the image height and 20px for the "height" of the graph itself (how tall it is). Other parameters not specified are "backgroundColor" as a hexidecimal string (default is white) and "legend" a boolean that tells the class whether to draw a legend or not (default is true). Personally I prefered a legend rendered in HTML since it gave me the control of styling with CSS and the benefit of being more accessible. So I also added the "legend" function to the Helper which does just that:



<?php if ($pieChart->create($eq_data)) {
    echo 
$pieChart->draw(18010020'#ffffff'0); 
    echo 
$pieChart->legend(); 
?>

The "legend" function takes an optional parameter "class" which is the className applied to the bounding div of the legend as a string (default is legend). The legend itself is an unordered list within the aforementioned div. An example of the HTML (for styling) could be:



<div class='legend'>
    <ul>
        <li><img src="/img/eq_pie/00dfbf30c9377fa1bbc0a247fb832f23.png" alt="#E5E5E5" /> Inglés <span>60.0%</span></li>
        <li><img src="/img/eq_pie/164e9adadaee35857bc637a77b4ed7c5.png" alt="#C1D0D6" /> Español <span>40.0%</span></li>
    </ul>
</div>

Note: The legend function actually creates colored images to use for the key - the benefit of this? You can print the chart and the colors of the legend key will be retained!

Report

More on Helpers

Advertising

Comments

  • alkemann posted on 12/09/08 02:36:12 AM
    There isn't a need for you to interpret this, it's pretty clear what it means. Which is, you should not make money out of using the free version. If you put it in a commercial product, you must buy the commercial version. Yes, this includes using it in a web app that someone is paying you to develop or that your company is making as a product to sell or profit from.
    • rloaderro posted on 05/12/09 06:56:05 PM
      There isn't a need for you to interpret this, it's pretty clear what it means.
      I'm sorry, but I have to disagree. These licenses are pretty clear:

      http://www.opensource.org/licenses/alphabetical
      In the case of eq_pie, the author wrote "Free for non-commercial use" on the PHP classes site. In the class itself he wrote "Feel free to use it, a reference to me would be nice". Since there is no commercial version to buy I think that does leave a lot to interpretation. As someone who develops and releases open-source software free for use the only thing that I would not like is for someone to re-package my work and sell it for a profit. But "this includes using it in a web app that someone is paying you to develop" frankly is bullshit.
  • euromark posted on 06/27/08 05:53:17 AM
    i added a function in the piechart.php helper:

    Helper Class:

    <?php 
    function setColor(){
            
    $anz=$this->anzahl;
            for(
    $i=0;$i<$anz;$i++) {
                if (empty(
    $this->data[$i][2]) || strlen($this->data[$i][2])<7){$this->data[$i][2]=$this->eq_pie->getColor($i);}   
            }
        }
    ?>

    and the array to create the pie now looks like that:

    $eq_data = array();

    $eq_data[] = array('English', 10); // no third parameter needed ;-)
    $eq_data[] = array('Spanish', 5);
    $eq_data[] = array('German', 25);

    $this->set('eq_data', $eq_data); 

    if ($piechart->create($eq_data)) {...}
  • euromark posted on 06/27/08 05:27:49 AM
    it didnt work right away, so i checked the source code of the browser, and there it was:

    after changing all DS-constants to '/' it worked.
    but i dont think this is good programming style.
    does anybody know why the wrong DS is showing up?

    thx, mark


    PS: the class itself has a function to create colors
    i think, it makes sense to use it (so you dont have to come up with them while creating a pie..)
  • lecterror posted on 01/17/08 07:32:00 AM
    Great work, simple and easy, useful article.
login to post a comment.