Google image charts in the PHP MVC pudding!

The other day I had to implement Google Image charts using a MVC framework. I could not find any information easily so came up with this idea which I wanted to share with you. I am sure that there are others who have also thought about this.

So in essence, I had a controller, where the action would:

1. Get the charting information from the model
2. Prepare the post packet for the call to Google charts api
3. Display the chart image in the view.

In this case my view contains in addition to other markup an image tag to receive the chart image:

<img src="/myController/myAction/" width="xxx" height="yyy">

The source attribute of an image is any URL and the only requirement is that the return data be of type ‘image’. In this case the URL follows the standard Controller/Action format.You can add parameters to this URL in case you wanted to something special in your action.

My action in the controller is something like this:

public function myAction(){
        //data from your model
        //for simplicity I have created an array for demo
	$rows = array(array('Count' => 2, 'Date' => '08/09/2010'), 
                array('Count' => 2, 'Date' => '08/09/2010'), 
                array('Count' => 2, 'Date' => '08/09/2010'), 
                array('Count' => 2, 'Date' => '08/09/2010'),
	$chd = 't:';
	$chxl = '0:|';
	$chxp = '0,';
	$xoff = 35;
	foreach($rows as $row){
		$chd .= $row['Count'] . ',';
		$chxl .= urlencode($row['Date']) . '|';
		$chxp .= $xoff . ',';
		$xoff = $xoff * 2;
	}
	$chd = rtrim($chd, ',');
	$chxl = rtrim($chxl, '|');
	$chxp = rtrim($chxp, ',');
	
	  // Add data, chart type, chart size, and scale to params.
	  $chart = array(
	    'cht' => 'bvg',
	    'chs' => '600x500',
	    'chxr' => '1,0,7',
	    'chbh' => '50',
	    'chds' => '0,7',
	    'chxp' => $chxp,
	    'chxt' => 'x,y',
	    'chxs' => '2,000000,12',
	    'chxl' => $chxl,
	    'chtt' => 'Movies VS. Date',
	    'chd' => $chd);
		
		$p = '';
		foreach($chart as $k => $v){
			$p .= "&{$k}={$v}";
		}
		
	    //make the call to Google
            $url = 'https://chart.googleapis.com/chart?chid=' . md5(uniqid(rand(), true));
	    
	    $ch = curl_init();
	    // set URL and other appropriate options
	    curl_setopt($ch, CURLOPT_URL, $url);
	    curl_setopt($ch, CURLOPT_HEADER, 0);
	    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
	    curl_setopt($ch, CURLOPT_POST, 1);
	    curl_setopt($ch, CURLOPT_POSTFIELDS, $p);	
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	    curl_setopt($ch, CURLOPT_VERBOSE, 1);
	    curl_setopt($ch, CURLOPT_TIMEOUT, 180);   
	
	    // grab URL and pass it to the browser
	    $response = curl_exec($ch);
	    $errorNo = curl_errno($ch);
	
	    if ($errorNo !== 0) {
	        $info = curl_getinfo($ch);
	        curl_close($ch);
	        error_log ("ErrorNo: {$errorNo} Curl Info: " . print_r($info, true));
	    }
	
	    curl_close($ch);
	
	   echo $response;

So, when the view loads , the src attribute makes the call and an image is returned. Nice and simple.

But then what happens if in this same view I need to select different type of charts?

In that case my view is now something like this:

<script>
	$(document).ready(function(){
		$('#chart_type_select').change(function(){
			var type = $(this).val();			
			$('#chart_draw').attr('src', '/myController/myAction?type=' + type);
		})	
	});
</script>


<select id='chart_type_select'>
  <option value =''>Select Chart</option>
  <option value ='1'>Chart Type 1</option>
  <option value ='2'>Chart Type 2</option>
</select>

<img id="chart_draw" width="xxx" height="yyy">

All I do in this case is switch the src attribute of the image tag which now also has a get parameter, ‘type’. You can now acquire this parameter in your action and process a different chart! No page refreshes!

Whenever we do not want page refreshes the usual temptation is of course to use an AJAX call. However if you do that you will run into cross domain issues and using AJAX with large binary payloads is not recommended.

I hope this idea of using an image tag instead of an AJAX call helps you.

As always I look forward to your comments.

Happy programming!

-Jayesh

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s