Comments

Saturday, April 14, 2012

Using HighCharts with php , MySQL and CodeIgniter

Posted by on Saturday, April 14, 2012 Read our previous post
Highcharts is a charting library which helps to display interactive Javascript charts on webpages. But our tutorial is how to make use of Highcharts with php, MySQL and CodeIgniter. 

While working on a project I found out that HighCharts is the best to display graphs on webpage as it has less overhead and requires less space. But the biggest challenge was to implement it using php  and not jQuery. We will implement it using MVC pattern as CodeIgniter follows the same.

Here is how we will be going about leaning this :

1. We will need HighCharts Library for CodeIgniter and HighChart config file. That we have defined below. (library is pretty long)
2. We will be making Models, Controllers and Views to display the Chart taking the values from MySQL. (if you want to check controllrt, model and view then directly go to the end)



So before we go ahead you will need to download the Javascript file of HighChart. Click Here (downloasd HighChart and not HighStock)

Below is the library and config file that you will need to COPY & PASTE  to a .php file. Name the librayr file as HighCharts_lib.php and config file as HighCharts_config.php.

HighChart Library for CodeIgniter

Below is the library file, you will need to put this 

HighChart_lib.php : 


<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Highcharts {
    
    private static $chart_id = 0;
    
    private $shared_opts     = array(); // shared grah data
    private $global_opts    = array(); // All stocked graph data
    private $opts                    = array(); // current graph data
    private $replace_keys, $orig_keys, $serie_index = 0;
    
    public $js_chart_name = 'chart'; // name of the js var    
    
    public function __construct($config = array())
    {                
        if (count($config) > 0) $this->initialize($config);
    }
    
    public function initialize($config = array(), $config_path = 'highcharts')
    {
        if (is_string($config)) // string means "load this template"
        {
            $ci =& get_instance();
            $ci->config->load($config_path);
            
            $config = $ci->config->item($config);
            
            if (count($config) > 0)
            {
                $this->opts = $this->set_local_options($config);
            }
            
        }
        if (isset($config['shared_options']) AND empty($this->shared_opts))
        {
            $this->shared_opts = $config['shared_options'];
            unset($config['shared_options']);
        }
        
        if (! isset($this->opts['series'])) $this->opts['series'] = array();
        if (! isset($this->opts['chart']['renderTo'])) 
            $this->opts['chart']['renderTo'] = 'hc_chart';

        return $this;
    }

    public function set_global_options($options = array())
    {
        if (! empty($options)) 
            $this->shared_opts = $this->set_local_options($options);
        
        return $this;
    }

    public function __call($func, $args)
    {
        if (strpos($func,'_'))
        {
            list($action, $type) = explode('_', $func);
        
            if (! isset($this->opts[$type]))
            {
                $this->opts[$type] = array();
            }
            switch ($action)
            {
                case 'set':
                $this->opts[$type] = $this->set_local_options($args[0]);
                break;
                
                case 'push':
                $this->opts[$type] += $this->set_local_options($args[0]);
                break;
                
                case 'unset':
                $this->unset_local_options($args, $type);
                break;
            }
        }
        
        return $this;
    }
    
    private function set_local_options($options = array(), $root = array())
    {
        foreach ($options as $opt_key => $opt_name)
        {        
            if(is_string($opt_key))
            {
                if(is_object($opt_name))
                {
                    $root[$opt_key] = array();
                    $root[$opt_key] = 
                    $this->set_local_options($opt_name, $root[$opt_key]); 
                }
                else $root[$opt_key] = $this->encode_function($opt_name);
            }
        }
        return $root;
    }
    
    private function unset_local_options($options = array(), $type)
    {        
        foreach ($options as $option)
        {
            if (array_key_exists($option, $this->opts[$type]))
            {
                unset($this->opts[$type][$option]);
            }
        }
    }
    
    public function set_title($title = '', $subtitle = '')
    {
        if ($title) $this->opts['title']['text'] = $title;
        if ($subtitle) $this->opts['subtitle']['text'] = $subtitle;

        return $this;
    }
    
    function set_axis_titles($x_title = '', $y_title = '')
    {
        if ($x_title) $this->opts['xAxis']['title']['text'] = $x_title;
        if ($y_title) $this->opts['yAxis']['title']['text'] = $y_title;
        
        return $this;
    }

     function set_axis_ymax( $y_max)
    {
        if ($y_max) $this->opts['yAxis']['max'] = $y_max;

        return $this;
    }

     function set_axis_ymin( $y_min)
    {
        if ($y_min) $this->opts['yAxis']['min'] = $y_min;

        return $this;
    }

     function set_axis_ytype( $type = '')
    {
        If($type and is_string($type)) $this->opts['yAxis']['type'] = $type;

        return $this;
    }

                
     function set_axis_xtype( $type = '')
    {
        If($type and is_string($type)) $this->opts['xAxis']['type'] = $type;

        return $this;
    }

     function set_axis_xmax($x_max)
    {
        if ($x_max) $this->opts['xAxis']['max'] = $x_max;

        return $this;
    }
    
    public function render_to($id = '')
    {
        $this->opts['chart']['renderTo'] = $id;

        return $this;
    }
    
    public function set_type($type = '')
    {
        if ($type AND is_string($type)) $this->opts['chart']['type'] = $type;
        
        return $this;
    }
    
    
    public function set_dimensions($width = null, $height = null)
    {
        if ($width)  $this->opts['chart']['width'] = (int)$width;
        if ($height) $this->opts['chart']['height'] = (int)$height;
        
        return $this;
    }
    
    public function set_serie($options = array(), $serie_name = '')
    {
        if ( ! $serie_name AND ! isset($options['name']))
        {
            $serie_name = count($this->opts['series']);
        }
        // override with the serie name passed
        else if ($serie_name AND isset($options['name']))
        {
            $options['name'] = $serie_name;
        }
        
        $index = $this->find_serie_name($serie_name);
                    
        if (count($options) > 0)
        {
            foreach($options as $key => $value)
            {
                    $value = (is_numeric($value)) ? (float)$value : $value;
                    $this->opts['series'][$index][$key] = $value;
            }
        }
        return $this;
    }
    
    public function set_serie_options($options = array(), $serie_name = '')
    {
        if ($serie_name AND count($options) > 0)
        {
            $index = $this->find_serie_name($serie_name);
                        
            foreach ($options as $key => $opt)
            {
                $this->opts['series'][$index][$key] = $opt;
            }
        }
        return $this;
    }
    
    
    public function push_serie_data($value = '', $serie_name = ''){
        
        if ($serie_name AND $value)
        {
            $index = $this->find_serie_name($serie_name);
            
            $value = (is_numeric($value)) ? (float)$value : $value;
                
            $this->opts['series'][$index]['data'][] = $value;
        }
        return $this;
    }
    
    private function find_serie_name($name)
    {
        $tot_indexes = count($this->opts['series']);
        
        if ($tot_indexes > 0)
        {
            foreach($this->opts['series'] as $index => $serie)
            {
                if (isset($serie['name']) AND 

                    strtolower($serie['name']) == strtolower($name))
                {
                    return $index;
                }
            }
        }
        
        $this->opts['series'][$tot_indexes]['name'] = $name;
        
        return $tot_indexes;
    }

     public function export_file($filename){
         $this->opts['exporting']['enabled'] = True;
         $this->opts['exporting']['enableImages'] = True;
         $this->opts['exporting']['filename'] = $filename;
         $this->opts['exporting']['type']=  'image/jpeg';
         return $this;
        }
    
    public function push_categorie($value, $axis = 'x')
    {
        if(trim($value)!= '') 
           $this->opts[$axis.'Axis']['categories'][] = $value;

        return $this;
    }

         public function push_xcategorie($value)
    {

          $this->opts['xAxis']['categories'] = $value;

        return $this;
    }    

    public function from_result($data = array())
    {
        if (! isset($this->opts['series']))
        {
            $this->opts['series'] = array();
        }
                
        foreach ($data['data'] as $row)
        {
            if (isset($data['x_labels'])) 
                $this->push_categorie($row->$data['x_labels'],'x');
            if (isset($data['y_labels'])) 
                $this->push_categorie($row->$data['y_labels'],'y');
            
            foreach ($data['series'] as $name => $value)
            {    
                // there is no options, juste assign name / value pair
                if (is_string($value))
                {
                    $text = (is_string($name)) ? $name : $value;
                    $dat  = $row->$value;
                }
                
                // options are passed
                else if (is_array($value))
                {
                    if (isset($value['name']))
                    {
                        $text = $value['name'];
                        unset($value['name']);
                    }
                    else
                    {
                        $text = $value['row'];
                    }
                    $dat = $row->{$value['row']};
                    unset($value['row']);
                    
                    $this->set_serie_options($value, $text);
                }
                
                $this->push_serie_data($dat, $text);
            }
        }
        return $this;
    }
    
    public function add($options = array(), $clear = true)
    {
        if (count($this->global_opts) <= 
            self::$chart_id AND ! empty($this->opts['series']))
        {
            if (is_string($options) AND trim($options) !== '')
            {
                $this->global_opts[$options] = $this->opts;
            }
            else
            {
                $this->global_opts[self::$chart_id] = 
                (count($options)> 0) ? $options : $this->opts;
            }
        }
        
        self::$chart_id++;    
        
        if ($clear === true) $this->clear();
                    
        return $this;
    }
    
    public function get($clear = true)
    {
        $this->add();
        
        foreach ($this->global_opts as $key => $opts)
        {
            $this->global_opts[$key] = $this->encode($opts);
        }    
        
        return $this->process_get($this->global_opts, $clear, 'json');
    }
    
    public function get_array($clear = true)
    {
        $this->add();
        
        return $this->process_get($this->global_opts, $clear, 'array');
    }
    
    public function encode($options)
    {
        $options = str_replace('\\', '', json_encode($options));
        return str_replace($this->replace_keys, $this->orig_keys, $options);
    }
    
    private function process_get($options, $clear, $type)
    {
        if (count($this->shared_opts) > 0)
        {
            $global = ($type == 'json') ? 
            $this->encode($this->shared_opts) : $this->shared_opts;
            
            $options = array('global' => $global, 'local' => $options);
        }
        
        if ($clear === true) $this->clear();
        
        return $options;
    }
    
    public function render()
    {
        $this->add();
        
        $i = 1; $d = 1; $divs = '';

        $embed  = '<script type="text/javascript">'."\n";
        $embed .= '$(function(){'."\n";
        
        foreach ($this->global_opts as $opts)
        {
            if (count($this->shared_opts) > 0 AND $i === 1)
      {
      $embed.='Highcharts.setOptions('.$this->encode($this->shared_opts).');'."\n";
      }

      if ($opts['chart']['renderTo'] == 'hc_chart')
      {
        $opts['chart']['renderTo'] .= '_'.$d;
        $d++;
      }
            
        $embed .= 'var '.$this->js_chart_name.'_'.$i.
                  ' = new Highcharts.Chart('.$this->encode($opts).');'."\n";
            $divs  .= '<div id="'.$opts['chart']['renderTo'].'"></div>'."\n";
            $i++;
        }
        
        $embed .= '});'."\n";
        $embed .= '</script>'."\n";
        $embed .= $divs;
        
        $this->clear();
                
        return $embed;
    }
    
    
    public function clear($shared = false)
    {
        $this->opts = array();
        $this->opts['series'] = array();
        $this->opts['chart']['renderTo'] = 'hc_chart';
        $this->serie_index = 0;
        
        if ($shared === true) $this->shared_opts = array();
        
        return $this;
    }
    
    private function encode_function($array = array())
    {
        if (is_string($array)) {
            $array = $this->delimit_function($array);
        }
        else {
            foreach($array as $key => $value) {
                if (is_array($value)) {
                    $this->encode_function($value);
                }
                else {
                    $array[$key] = $this->delimit_function($value);
                }                
            }
        }
        return $array;
    }
    
    private function delimit_function($string = '')
    {
        if(strpos($string, 'function(') !== false)
        {
          $this->orig_keys[] = $string;
          $string = '$$' . $string . '$$';
              $this->replace_keys[] = '"' . $string . '"';
        }
        return $string;
    }

}

?>

NOTE :

Copy the above code and put to HighCharts_lib.php and put this file in the library folder.




HighCharts Config for CodeIgniter

Below is the code for config file :

HighCharts_config.php :


<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

// shared_options : highcharts global settings, like interface or language
$config['shared_options'] = array(
    'chart' => array(
        'backgroundColor' => array(
            'linearGradient' => array(0, 0, 500, 500),
            'stops' => array(
                array(0, 'rgb(255, 255, 255)'),
                array(1, 'rgb(240, 240, 255)')
            )
        ),
        'shadow' => true
    ),
    'exporting' => array(
        'enabled' =>true,
        'enableImages' => true,
        'buttons' => array(
            'exportButton' => array (
                'enabled' =>true
            )
        )
    ),
        
);

// Template Example
$config['chart_template'] = array(
    'chart' => array(
        'renderTo' => 'graph',
        'defaultSeriesType' => 'column',
        'backgroundColor' => array(
            'linearGradient' => array(0, 500, 0, 0),
            'stops' => array(
                array(0, 'rgb(255, 255, 255)'),
                array(1, 'rgb(190, 200, 255)')
            )
        ),
     ),
     'colors' => array(
          '#ED561B', '#50B432'
     ),
     'credits' => array(
         'enabled'=> true,
         
         'text'    => 'Code 2 Learn',
        'href' => 'www.code2learn.com'
     ),
    'exporting' => array(
        'enabled' =>true,
        'enableImages' => true,
        'buttons' => array(
            'exportButton' => array (
                'enabled' =>true
            )
        )
    ),
     'title' => array(
        'text' => 'Template from config file'
     ),
     'legend' => array(
         'enabled' => false
     ),
    'yAxis' => array(
        'title' => array(
            'text' => 'population'
        )

    ),
    'xAxis' => array(
        'title' => array(
            'text' => 'Countries'
        )
    ),
    'tooltip' => array(
        'shared' => true
    )
);

?>

NOTE :

Copy the code and put it in HighCharts_config.php file and then put that file inside the CONFIG Folder.

We have now defined the two files i.e. library file and config file.

Now lets get started and generate a chart with data taken from mysql db.


Controller


Controller receives user input and initiates a response by making calls on model objects. A controller accepts input from the user and instructs the model and a view port to perform actions based on that input.

Now we write the Controller code which will take data from DB using the Models and will rendering the Charts on webpage using Views.

Application.php :

<?php

class Application extends CI_Controller {

    function Application() {
        parent::__construct();
        $this->load->library('HighCharts_lib.php');
    }


private function index(){
        $data['charts'] = $this->getChart($studentName);
        $this->load->view('charts',$data);
}

private function getChart($stuName) {

        $this->highcharts->set_title('Name of Student :' . $stuName);
        $this->highcharts->set_dimensions(740, 300); 
        $this->highcharts->set_axis_titles('Date', 'Age');
        $credits->href = base_url();
        $credits->text = "Code 2 Learn : HighCharts";
        $this->highcharts->set_credits($credits);
        $this->highcharts->render_to("content_top");

        $result = $this->student_name->getStudentDetails($stuName);

            if ($myrow = mysql_fetch_array($result)) {
                do {
                    $value[] = intval($myrow["age"]);
                    $date[] = ($myrow["date"]);
                } while ($myrow = mysql_fetch_array($result));
            }

            $this->highcharts->push_xcategorie($date);

            $serie['data'] = $value;
            $this->highcharts->export_file("Code 2 Learn Chart".date('d M Y')); 
            $this->highcharts->set_serie($serie, "Age");

            return $this->highcharts->render();

        }
    }

?>

Functions used above are defined in the library, they are :

* set_title($var) : Sets the title of the Chart.
* set_axis_titles($x, $y) : Sets the title of the axis i.e x and y axis resp.
* set_dimension($width, $height)
* set_serie($serie, "Name") : This is the value that you want to be displayed on the chart.
* renderTo : The HTML element where the chart will be rendered. If it is a string, the element by that id is used. The HTML element can also be passed by direct reference. Defaults to null.


Model


Model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller). In event-driven systems, the model notifies observers (usually views) when the information changes so that they can react.


<?php

class Student_Name extends CI_Model {

    function getStudentDetails($stuName) {
        $query = "PUT YOUR QUERY";
        $result = mysql_query($query);
        return $result;
    }
}

?>

Above is the code for the MODEL which will send the prices of that particular model to the CONTROLLER which will put it into the chart.


View 


View renders the model into a form suitable for interaction, typically a user interface element. Multiple views can exist for a single model for different purposes. A view port typically has a one to one correspondence with a display surface and knows how to render to it.



<html>
    <head>
        <script type="text/javascript" src="../../js/highcharts.js"></script>
        <script type="text/javascript" src="../../js/exporting.js"></script>
    </head>
    <body>
        <div class="boxLarge top">
            <h3 class="header">Price History</h3>
            <div class="content top" id="graph">
                <?php if(isset($charts)) echo $charts;  ?>
            </div>
        </div>
    </body>
</html>

If you put all the codes together in a proper manner than it will generate a graph which will same as shown below but with diff values as your mobile might be different.

© 2010 Code 2 Learn