Drawing pictures in PHP requires a fair amount of thinking as it is, so can you image how hard it is to draw graphs? Well, surprisingly it's quite easy: graphs are after all just groups of mathematical functions displayed in a graphical format. Having said that, there's little point re-inventing the wheel: there are already pre-written scripts that graphics for us and do so in a far more advanced way than we could ever do ourselves.
By re-using other people's work, we can concentrate on the important things, such as the actual content and unique programming for our site! The best graph creation toolkit around is called JpGraph, and it's available free for non-commercial use for download from http://www.aditus.nu/jpgraph/jpdownload.php.
Go ahead and download JpGraph to your public HTML directory. You need to edit the file jpg-config.inc so that the CACHE_DIR, TTF_DIR, and USE_CACHE variables are properly set - the file has copious amounts of comments for explaining it. You should also check your php.ini file and make sure "register_long_arrays" is set to On rather than Off - most versions of JpGraph require this to function. Once you have it configured try one of the examples from the Examples directory to make sure it works. There is a lot of excelent documentation included and online to help you if you have problems; there's little point me reproducing it here.
Let's take a look at a simple graph:
<?php include 'jpgraph.php'; include 'jpgraph_bar.php'; $array = array(1, 2, 4, 5, 3, 3.5, 2, 1.1); $graph = new Graph(600,350); $graph->SetScale('textint'); $plot = new BarPlot($array); $graph->Add($plot); $graph->Stroke(); ?>
That breaks down neatly into two lines of including JpGraph libraries and six actual lines, and I hope you'll agree that the result is actually quite impressive!
Now onto how it works. The two include files are first the core JpGraph file, jpgraph.php, and the particular file for the type of chart we wish to draw. Functionality is split up like because the source code for each type of chart is usually at least 10kb, and it would be a waste to include too much more code than was used. As we'll be drawing a bar chart for our first graph we need to include the file jpgraph_bar.php.
The third line of the script (the first line of actual code!) is where we define the data we want to graph. This is stored in a simple array with one value per element. Note that I've mixed up integers and floating-point numbers.
The next two lines are where we set up the graph. JpGraph is object-oriented, which means everything is done in re-usable classes. As a result we need to create a new Graph object, passing in the width and height of the graph, and store the result. The following line sets up the scales of the graph, and takes a variety of parameters. "Textint" is the most common, and means "space the X axis according to the the text for the fields, and the Y column using normal integers". It's done this way so you can have logarithmic Y axes and other options, but you will nearly always want to stick with textint.
Moving on, lines six and seven in the script create our BarPlot object, passing in our array of values, and adds that to our graph. Finally the last line calls the Stroke() function of our graph object, which draws and outputs our image, cleans up any resources, and optionally also saves it into the cache for later use. Thanks to that one function doing so many things, that's the end of our script!
Although it's very simple, the output is nonetheless pleasing. However, there are a large number of simple changes we can make to style it up so that it could fit into a proper site design. Note that I've only included these things all in one script for demonstration - I don't suggest you implement all these graphical ideas altogether, because it does detract from the data if you're not careful!
<?php include 'jpgraph.php'; include 'jpgraph_bar.php'; $array = array(3, 4, 5, 6, 2, 1, 2); $graph = new Graph(600,350); $graph->SetScale('textint'); $graph->SetBackgroundImage('space.png'); $graph->SetBackgroundImageMix(70); $graph->SetShadow(); $graph->SetMarginColor("#5599FF"); $graph->title->Set("Much prettier!"); $graph->subtitle->Set("Don't you think so?"); $plot = new BarPlot($array); $plot->SetFillColor(array('#FFFF00', '#FFEE00', '#FFDD00', '#FFCC00', '#FFBB00', '#FFAA00', '#FF9900')); $graph->Add($plot); $graph->yaxis->SetTitle("Foobars", "middle"); $graph->xaxis->SetTitle("Days of the week", "middle"); $days = $gDateLocale->GetShortDay(); $graph->xaxis->SetTickLabels($days); $graph->Stroke(); ?>
About half the code there is new. The first five lines are basically the same (I've tweaked the data array), but it goes off on a tangent from there.
First up, SetBackgroundImage() takes a filename to use as the background for the graph part of the output - that's everything where the bars are showing. SetBackgroundImageMix() takes a number between 0 and 70 for how opaque the image should be - 100 is total opaqueness (that is, the picture is totally visible) and 0 is total transparency. Setting it to 70 will show most of the picture, blended against the background colour of the chart, which is white by default.
The SetShadow() call takes no parameters by default, and simply enables a thin greyish line around the edge of the chart to give it the somewhat weak appearance of it floating above the page. The next line is also easy: SetMarginColor() takes a colour parameter and uses that to shade the border around the graph. The colour I've used is equivalent to light blue.
Next, the two calls to the Set() method sets the text of the title and subtitle for the graph. This is just eye candy, really.
Like last time, a new BarPlot() object is created, but this time I've set the fill colours for the bars using the SetFillColor() function. This takes an array of colours to use, so I've defined one colour for each of my values. The BarPlot is then added to the graph.
With actual data in the graph, there's now an X and Y axis in our graph, so the following two lines set up titles for these two. If you were really bad at maths at school, here's a reminder: the X axis is horizontal, and the Y axis is vertical.
The next two lines are a cheeky little addition I dropped in there to add a bit of spice to the script. $gDateLocale is a variable set automatically by JpGraph to an object containing various information about days and months in the current locale, and it's very helpful because it's quite common to use days or months as field names in the X axis. The small "g" at the front of the variable is there to remind you it's global - declared for you elsewhere, and so you're free to use it.
What the first line does is call the GetShortDay() function of the locale object, which returns an array of common abbreviations for the days of the week, eg "Sun", "Mon", "Tue", etc. The array is indexed by the number of the day in the week, which means that 1 is Sunday and 6 is Saturday. This array is then used as the parameter for the SetTickLabels() function, which assigns it to the X axis - the names of the X-axis rows are used to index into the $days array.
Finally the Stroke() function is used to output the graph. Although the code was twice the size, I hope you'll agree it was worth it - the graph looks much better now.
The last thing we're going to build is a 3D pie chart, and, by clever design more than happy co-incidence, this is done largely using the same code as we already have. Take a look at this:
<?php include 'jpgraph.php'; include 'jpgraph_pie.php'; include 'jpgraph_pie3d.php'; $array = array(3, 4, 5, 6, 2, 1, 2); $graph = new PieGraph(500,350); $graph->SetShadow(); $graph->title->Set("Pie charts"); $graph->subtitle->Set("Changing from one graph style to another couldn't be easier!"); $graph->SetScale('textint'); $plot = new PiePlot3D($array); $graph->Add($plot); $graph->Stroke(); ?>
The code is nearly totally identical to our previous graph code, with the following minor changes: jpgraph_pie.php and jpgraph_pie3d.php are now included, the actual graph is of type PieGraph rather than just Graph, and the data array is of type PiePlot3D rather than BarPlot. Those are the only changes, though - what a big difference for such little work!
If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!
Next chapter: Working with RTF >>
Previous chapter: Keeping your files small
Home: Table of Contents
Copyright ©2015 Paul Hudson. Follow me: @twostraws.