A while ago I wrote about making use of information collected by websites – I find graphs a great way to do this. And while there are lots of great graphing objects, or tools available today, it can be a hectic scene to try and find a free one that you want for basic use. So quick modifications to existing code can sometimes be exactly what you need! Below is the code that was used to create the graphs seen in that previous post.
At the top of my graphing file, I’ve added two functions that I need to make use of while processing input from the user:
//convert the submitted string to be only an integer
function parseInt($string) {
if(preg_match('/(\d+)/', $string, $array)) {
return $array[1];
} else {
return 0;
}
}
/* given variable intVal, make sure it sits between a minimum number, and a maximum number! */
function bound($intVal, $min, $max){
$thisVal = parseInt($intVal);
if ($thisVal < $min){
$thisVal = $min;
}
if ($thisVal > $max){
$thisVal = $max;
}
return $thisVal;
}
Then I actually grab the input from the user – as this will usually be in within an IMG tag, all submitted parameters are going to be part of a GET request:
//How many points on the graph are desired
$idealRows = bound($_GET['points'], 5, 20);
//The currency to peg against
$baseValue = bound($_GET['base'], 1, 5);
//The currency that varies against the peg
$floatValue = bound($_GET['float'], 1, 5);
//How many days in the past to start the graph from
$skipDays = bound($_GET['skip'], 0, 45);
Now that we know what the user wants the graphic to do, we can pull the necessary information out of the database. I have modeled this for connectivity to MySQL, and have abstracted out table components so that you can easily adapt this to any table that you want:
/* Get the daily currency information over the user specified period */
$currencyQuery = "SELECT field1, field2 FROM tableName WHERE currencyRefCode='".$baseValue."' AND currency2RefCode='".$floatValue."' ORDER BY sequenceElement DESC LIMIT ".$skipDays.", ".$idealRows.";";
After you have structured your query to your database, then you need to run it and extract the data row by row:
//Run the SQL query
$cqRes = mysql_query($currencyQuery);
/* Find out how many rows were returned by SQL */
$num_entries = mysql_num_rows($cqRes);
/* As long as there was more than one row we can do some work! */
if ($num_entries > 0){
/* As our currency table is ordered the wrong way round (i.e. it goes back in time) we need to start from the end and work backwards! */
$loadPos = $num_entries - 1;
//While rows exist in the table, extract data
while ($cqRow = mysql_fetch_array($cqRes, MYSQL_NUM)){
//Store the floating value in an array
$nt["currVal"][$loadPos] =$cqRow[0];
/* Store the date of this value in an array, but crop the MYSQL datestamp down to only the parts that we want using substr */
$nt["month"][$loadPos] = substr($cqRow[1], 6, 5);
/* Move the array pointer back a value */
$loadPos--;
}
}else{
// Woops! Nothing could be found using this query!
die ("Invalid currency query");
}
Now that the data has been made available, preparations for the actual image canvas can be made:
$x_gap=40; // The gap between each point in y axis
$x_max=$x_gap*($num_entries+1); /* Maximum width of the graph or horizontal axis */
$top_gap = 20; /* The minimum distance to keep from the top of the image */
$y_elev = 30; /* The distance to elevate the graph from the bottom of the image */
$y_max = 150; /* The maximum height of the graph canvas */
/* Determine the lowest point and highest point that will be graphed */
$minVal = min($nt["currVal"]);
$maxVal = max($nt["currVal"]);
/* Now a scaling factor will be determined - this allows the graph to pronounce differences between values, otherwise the graph would look quite boring! */
if ($maxVal - $minVal ==0){
/* There is no difference! So this graph will be a straight line */
$scaleFact = 1;
}else{
/* There is some difference, so this graph will have ups and downs */
$scaleFact = $maxVal-$minVal;
}
/* Determine the full scaling factor to be used by determining the largest pixel difference between points */
$scaler=($y_max-$top_gap)/($scaleFact);
So this has now allowed us to determine the size of the canvas, and the distance between points vertically and horizontally – so prepare the image canvas in PHP:
//create the canvas
$im = @ImageCreate ($x_max, $y_max+$y_elev)
//if that failed, then kill the script
or die ("Cannot Initialize new GD image stream");
//set up all the colours (image resource, R, G, B)
$background_color = ImageColorAllocate ($im, 255, 255, 255);
$text_color = ImageColorAllocate ($im, 233, 14, 91);
$graph_color = ImageColorAllocate ($im,25,25,25);
$grid_color = ImageColorAllocate ($im,125,125,125);
As the canvas is ready, the points have been loaded into an array, and the scaling factors are known, now we can actually plot each point onto the graph! By the way, I am using VenueMirror‘s currency objects here – and the added benefit that I get from that is that in this script is that they return things like currency codes. Above, where there is an SQL query – I would have actually used methods from the objects themselves to get the graphing points. If you copy/paste this code, it will break here – so please change yours to reflect the currency codes, or other data descriptors here!
$x1=0;
$y1=0;
$first_one=true;
/* Put the title of the image into the image! */
ImageString($im,2,5,5,"How many ".$floatCurr->getCurrCode()." buy 1 ".$baseCurr->getCurrCode()." - http://www.venuemirror.com/blog/74/useful-currency-information-by-accident",$graph_color);
/* Start walking through the array of points */
for($pos=0; $pos < $num_entries; $pos++){
$x2=$x1+$x_gap; // Shifting in X axis
$y2=$y_max-(($nt["currVal"][$pos]-$minVal)*$scaler); // Coordinate of Y axis
//Write the floating currency value to the image next to the point
ImageString($im,2,$x2,$y2,round($nt["currVal"][$pos],2),$graph_color);
// Drawing the grid vertically//
imageline ($im,$x2, $y_max,$x2,$y2,$grid_color);
ImageString($im, 2, $x2-($x_gap/2), $y_max+($y_elev/2), $nt["month"][$pos], $graph_color);
//Line above is to print month names on the graph
if(!$first_one){ // this is to prevent from starting $x1= and $y1=0
imageline ($im,$x1, $y1,$x2,$y2,$text_color); // Drawing the line between two points//
}
$x1=$x2; // Storing the value for next draw
$y1=$y2;
$first_one=false; // Now flag is set to allow the drawing
}
//Output the image
ImageJPEG ($im);
Credit also goes to this tutorial on Plus2Net, as that provides good insight on how to actually draw graphs. I took much of what they wrote (and their code), and rendered it into a complete actual example here.
Do you have anything that you’re looking to create report style graphs about? There are other features in PHP that let you make 3D bar charts, and pie charts, and we use them a lot for internal reporting. Do you need information on those too? If you have any examples of graphs that you’re making from internal data then please post links to them below!
Also, if you find any bugs, security holes, or other horrible things in this code then please let me know! Do you also want a full file to download?
Cheers!
K
P.S. I know that I said that I would post that the code the following day, but it’s a been a bit crazy recently – so I’m sorry about the delay!
Share on FacebookTags: php, user generated content, website
