Tutorial Details
- Topic: PHP, mySQL
- Difficulty: Beginner
- Estimated Completion Time: 60 minutes
This tutorial will teach you how to easily create drill-down charts in PHP using the LinkedCharts feature of FusionCharts.
Introduction
Presenting data in a graphical format always helps a lot in parsing the data efficiently. If the charts are interactive and linked, that’s even better.
Drill-down charts allow you to convert individual data plots (columns in column chart, pie slices in pie chart etc) of a chart into hotspots (or links).
These items, when clicked, can open new charts and you can navigate between these charts easily.
What are Linked Charts
Linked charts are a new and smart drill-down feature introduced in FusionCharts v3.2
Untiil now, these charts had individual data streams and were not completely tied together. What if all this data could be in one data stream and we could browse through these charts back and forth? Well, that’s exactly what LinkedCharts does. It’s a new and smart drill-down feature introduced in FusionCharts v3.2, that allows you to create unlimited levels of drill-down charts using a single data source. All the links originate from a parent chart and its respective data.
In this tutorial, we are going to take a practical look at integrating a chart with a sample application. The MySQL database will contain the data — a little PHP will work as an intermediary to fetch and process the data — and FusionCharts will handle the process of displaying the charts
To learn more about LinkedCharts and drill-down charts, take a look here. To briefly sum it up:
- Drill-down charts display data with the same settings as the parent chart by default.
- Additional configuration can also be done per drill-down level. You can change chart type and settings at each level of drill-down.
- Open links in a separate HTML container, jQuey dialog, lightbox, extJS window and more.
- Extensive events support using Javascript.
What are We Building?
Often times, we come across a situation where we want to monitor the growth of new users on our website. With that in mind, let’s make a small application that will show the number of registered users monthly / daily / hourly. Or, in simpler terms: how many users signed up in a given period of time?
We’ll make a simple bar chart, which is linked in such a way so that, initially, a monthly chart is shown. When someone clicks on one of the monthly bars, it changes to the daily chart, and again, subsequently, to the daily chart.
Requirements
- Any web server running PHP.
- MySQL database server, though, you can use any database of your choice.
- FusionCharts. If you do not have it, you can download an evaluation copy or buy it.
Step 0: Initial Setup
- Create an empty database, named
fctutorial
. You can also use an existing database, but be careful of overwriting tables. - Create an empty folder
fcdemo
in your web-server’s root directory (usually www).
Step 1: Preparing the Database
To keep it simple, we will use one table,
users
, which will contain the user information. We are only interested in the signup time of the users (the time they registered). So, we will create a table with only that information. Use the following SQL query to do so.- CREATE TABLE `users`
- (
- `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
- `Time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
- PRIMARY KEY (`ID`),
- KEY `Time` (`Time`)
- )
We have created a table with two fields:
ID
and time
. This time field contains the signup time of the users. Note that we have applied an INDEX
on the time field, because we will be doing a lot of WHERE
clause operations on it. Indexing helps performance in these situations.Connect to the Database
Let’s write a quick and small script that will help us to connect to database.
- <?php
- $db_host = 'localhost';
- $db_database = 'fctutorial';
- $db_username = 'root';
- $db_password = '';
- if ( ! mysql_connect($db_host, $db_username, $db_password))
- die ("Could not connect to the database server.");
- if ( ! mysql_select_db($db_database))
- die ("Could not select the database.");
- ?>
Change the database credentials according to your own settings. Next, save this file as
connect-to-database.php
in the fcdemo
folder we created.Inserting Sample Data
In a real world application, the
users
table will be populated over time. But, for demonstration purpose, we need to have some data in it. Let’s use a simple script to insert some random data into the table. Don’t worry if you don’t understand the following code; it’s not essential to this tutorial.- <?php
- //Connect to database
- require 'connect-to-database.php';
- //Set variables
- $MinTime = strtotime('2010-01-01');
- $MaxTime = strtotime('2010-12-12');
- $RecordsToInsert = 10000;
- //Generate random time and insert records
- for($i = 0; $i < $RecordsToInsert; $i++)
- {
- $RandomTime = rand($MinTime, $MaxTime);
- mysql_query("INSERT INTO `users` (Time) VALUES (FROM_UNIXTIME({$RandomTime}))") or die(mysql_error());
- }
- //Completed
- echo "Inserted {$RecordsToInsert} records.";
- ?>
Save this file as
generate-random-data.php
in the fcdemo
folder.
First, we connect to the database using the small script we wrote, then we set the minimum and maximum time from which randomly a time will be picked and inserted into the users table. Also, you can change the number of records to insert by changing
$RecordsToInsert
.
Next, we run this script to insert the data into the database. To do so, open your web browser and go to this URL :http://localhost/fcdemo/generate-random-data.php.
You should see
Inserted 10000 records
as the output.Step 2: Preparing the Skeleton HTML
Now, the actual process begins. We will create a basic HTML page that will hold the area where the chart will be shown. Here’s the basic HTML markup we will be using:
- <html>
- <head>
- <title>FusionCharts v3.2 - LinkedCharts with PHP Demo</title
- <script type="text/javascript" src="Charts/FusionCharts.js"></script>
- </head>
- <body>
- <div id="chartContainer">FusionCharts will load here</div>
- <script type="text/javascript"><!--
- var myChart = new FusionCharts( "Charts/Column3D.swf", "myChartId", "800", "400");
- myChart.setXMLUrl( "get-data.php?year=2010" );
- myChart.render( "chartContainer" );
- // -->
- </script>
- </body>
- </html>
Save this file as
demo.html
. What we have done is:- In
<head>
, we have imported the JavaScript file that is supplied with FusionCharts asFusionCharts.js
. You can find it in the Charts folder in the FusionCharts zip file. - In the
<body>
, we have created a<div>
element which will hold the chart. - Finally, we have written a small JavaScript snippet that essentially creates a FusionChart object with the following parameters:
a)Charts/Column3D.swf
specifies the FusionCharts chart SWF file to be used. For this demo, we are using the Column3D chart.
b)myChartId
tells the internal ID of the chart. This is helpful if we are creating more than one chart and need to reference them later.
c) The next two parameters,800
and400
, are the width and height of the chart. - The
myChart.setXMLUrl( "get-data.php?year=2010" );
bit defines the data source. Here, we tell it that the chart data will be XML and the URL of the data isget-data.php?year=2010
. Theget-data.php
is the script we will be writing in the next section.
So, we have used two files from the FusionCharts package. You need to copy and past them in the
fcdemo/Charts
folder to make our app work.Step 3: Writing the Backend
FusionCharts requires a source data in XML or JSON format. Let’s use the well-known XML data format, for this particular demo. The data file can contain both data for plotting, and cosmetic/functional configuration for the chart. Our objective is to create PHP code that can read the data from the database and generate an XML file like so:
- <chart caption="Monthly New Users for the Year: 2010" xAxisName="Months" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">
- <set value="486" name="1"/>
- <set value="443" name="2"/>
- <set value="553" name="3"/>
- <set value="550" name="4"/>
- <set value="634" name="5"/>
- <set value="622" name="6"/>
- <set value="710" name="7"/>
- <set value="772" name="8"/>
- <set value="850" name="9"/>
- <set value="1044" name="10"/>
- <set value="1175" name="11"/>
- <set value="761" name="12"/>
- </chart>
The XML is simply an XMLized version of data as normally shown in tabular format. The
chart
tag encapsulates all the data. The attributes in the opening tag here specify a few of the many possible disaply options, which instructs the underlying SWF file how to show the data. Here, we have specified the X and Y axis names, background colors, etc.
So, we will create the
get-data.php
file that will query the database for users, parse the results and create the XML file.- <?php
- //Sanitizing the input
- $Year = intval($_GET['year']);
- //Query to get users count for the give year.
- $Query = "SELECT MONTH(Time) AS Value, COUNT(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} GROUP BY Value";
- // fill the Result array with 0 values for each month
- $ResultArray = array_fill(1, 12, 0);
- // Prepare Chart Heading and X-AXIS label.
- $ChartHeading = 'Monthly New Users for the Year: '.$Year;
- $XaxisName = 'Months';
- //Connect to database
- require 'connect-to-database.php';
- //Query the database
- $QueryResult = mysql_query($Query);
- //Fetch results in the Result Array
- while($Row = mysql_fetch_assoc($QueryResult))
- $ResultArray[$Row['Value']]=$Row['Total'];
- //Generate Chart XML: Head Part
- $Output = '<chart caption="'.$ChartHeading.'" xAxisName="'.$XaxisName.'" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">';
- //Generate Chart XML: Main Body
- foreach($ResultArray as $key => $val) // key is month number (1-12)
- $Output .= '<set value="'.$val.'" name="'.$key.'"/>';
- //Generate Chart XML: Last Part
- $Output .= '</chart>';
- //Set the output header to XML
- header('Content-type: text/xml');
- //Send output
- echo $Output;
- ?>
Save this file as
get-data.php
. Let’s go over the code, bit by bit:- We sanitize and pass the value of
$_GET['year']
in the$Year
variable. - The query we are using is a simple query that counts the number of users registered, filtered by the
WHERE
clause to only users that were registered in the year passed by$Year
. The result isGROUP BY
- the value which is numeric. - Next, we prepare
$ResultArray
by filling it with 0 values for 1 to 12 keys. You’ll learn shortly why we do this. - We store the heading of the chart and the X-Axis label in appropriate variables.
- We call our database script and perform the actual query on the database.
- Next, we fetch the results, row by row, and insert the data into an array. As the SQL query does not return rows which have no number of users, we want 0 to appear here. That’s why we pre-filled
$ResultArray
with zeroes. This also assists us when automatically pre-sorting the array. - The next line of code deals with the process of creating the head section of the XML. The caption is set as
$ChartHeading
, which will serve as the heading of the chart. X and Y axis label are also set along with some color and formatting attributes. - Now, the main body of the XML file is prepared and stored in the
$Output
variable. It’s nothing but the simple name and value attributes in the <code><set> tag . - To complete the XML output, we close the
<chart>
tag. - As our output is XML, we set the content-type header as XML and echo the contents of our output variable.
Let's see what XML is generated by this code. Open your web browser and visit
http://localhost/fcdemo/get-data.php?year=2010
.
You should see XML data, with contents similar to what was shown at the beginning of this step.
Test it Out
Now that everything has been created, let's test out what we've created. Open your web browser and go tohttp://localhost/fcdemo/demo.html.
If you have followed everything correctly, you will see a working column3D chart with the monthly data.
Step 4: Converting it to a Drill-Down Chart with LinkedCharts
Our real objective today is to make our chart clickable, so that when someone clicks on any of the bars within the graph, the chart transitions, accordingly, to the daily chart.
There are two required methods to embed the child charts data into parent charts. We can append either the whole
data string
or just the data URL
for all the child charts within the parent data source. If data string
is used, the data for each descendant chart is embedded within the parent data source and linked using unique data identifiers. However, as in our case, there are many possible child charts (12 months x 30 days x 24 hours). In our case, we will use the data URL method. This way, we only need to link the data URL to the hotspots (the points which can be clicked, e.g. the bars in our chart).Modifying the PHP Code:
As we need the PHP code to fetch and generate XML for three kinds of chart: monthly, daily and hourly, we need to modify our existing code. Let's see the code first, and then we will dissect it piece by piece:
- <?php
- //Sanitizing the input
- $Type = $_GET['type'];
- $Year = intval($_GET['year']);
- $Month = intval($_GET['month']);
- $Day = intval($_GET['day']);
- //Months Names
- $MonthsNames = array(null, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
- //Prepare variables according to type-of-chart
- switch($Type)
- {
- default:
- case 'monthly':
- $Query = "SELECT MONTH(Time) AS Value, COUNT(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} GROUP BY Value";
- $ResultArray = array_fill(1, 12, 0); // fill the Result array with 0 values for each month
- $ChartHeading = 'Monthly New Users for the Year: '.$Year;
- $XaxisName = 'Months';
- break;
- case 'daily':
- $Query = "SELECT DAY(Time) AS Value, count(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} AND MONTH(Time)={$Month} GROUP BY Value";
- $ResultArray = array_fill(1, 31, 0); // fill the Result array with 0 values for each day
- $ChartHeading = 'Daily New Users for the Month: '.$MonthsNames[$Month].'/'.$Year;
- $XaxisName = 'Days';
- break;
- case 'hourly':
- $Query = "select HOUR(Time) AS Value, count(*) AS Total FROM `users` WHERE YEAR(Time)={$Year} AND MONTH(Time)={$Month} AND DAY(Time)={$Day} GROUP BY Value";
- $ResultArray = array_fill(0, 24, 0); // fill the Result array with 0 values for each hour
- $ChartHeading = 'Hourly New Users for the Date: '.$Day.'/'.$MonthsNames[$Month].'/'.$Year;
- $XaxisName = 'Hours';
- break;
- }
- //Connect to database
- require 'connect-to-database.php';
- //Query the database
- $QueryResult = mysql_query($Query);
- //Fetch results in the Result Array
- while($Row = mysql_fetch_assoc($QueryResult))
- $ResultArray[$Row['Value']]=$Row['Total'];
- //Generate Chart XML: Head Part
- $Output = '<chart caption="'.$ChartHeading.'" xAxisName="'.$XaxisName.'" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">';
- //Generate Chart XML: Main Body
- switch($Type)
- {
- default:
- case 'monthly':
- foreach($ResultArray as $MonthNumber => $value) // MonthNumber is month number (1-12)
- $Output .= '<set value="'.$value.'" name="'.$MonthsNames[$MonthNumber].'" link="newchart-xmlurl-get-data.php?type=daily&year='.$Year.'&month='.$MonthNumber.'"/>';
- break;
- case 'daily':
- foreach($ResultArray as $DayNumber => $value) // DayNumber is day (1-31)
- $Output .= '<set value="'.$value.'" name="'.$DayNumber.'" link="newchart-xmlurl-get-data.php?type=hourly&year='.$Year.'&month='.$Month.'&day='.$DayNumber.'"/>';
- break;
- case 'hourly':
- foreach($ResultArray as $HourNumber => $value) // HourNumber is hour (0-23)
- $Output .= '<set value="'.$value.'" name="'.$HourNumber.'"/>';
- break;
- }
- //Generate Chart XML: Last Part
- $Output .= '</chart>';
- //Set the output header to XML
- header('Content-type: text/xml');
- //Send output
- echo $Output;
- ?>
Now, to understand the changes:
- As earlier, we are sanitizing the input. Now, we have three kinds of charts, so the
GET
variable will tell us the kind of chart requested. It can be either monthly, daily or hourly. Similarly, we have$Month
and$Hour
, in addition to$Year
. - Next, we create an array of
$MonthNames
that will help us when converting the month number to its respective name easily. As an array is zero-based, and a month starts with 1, we set the first array item to null. - Now, depending on the type, the value of the
$Query, $ResultArray, $ChartHeading
and$XAsixName
variables are set, using theswitch
statement. If$Type
is undefined, the default case selects the monthly chart. - Next, we connect to the database, execute the query, fetch the results in the
$ResultArray
, and generate the first part of the XML file. - The main body of the XML is generated next. However, as it depends on the chart type, we have another switch statement. The real difference lies here:
- Monthly: Everything is the same, except for the link attribute. The link has the structure:
newchart-xmlurl-get-data.php
. Here,newchart
denotes that a new chart will be created.xmlurl
denotes that the data for the new chart is to be fetched from a URL (called thedata URL
). Whatever comes next becomes the part of this URL. The full link for the January bar becomes:newchart-xmlurl-get-data.php?type=hourly&Year=2010&Month=1
- Daily: It follows the same structure as the monthly part above. The link attribute now has a URL that has a variable for the day along with others.
- Hourly: As we do not want hourly chart to be clickable, the link attribute is not used here.
- Monthly: Everything is the same, except for the link attribute. The link has the structure:
- Finally, the
<chart>
tag is closed and the XML header is sent.
Save the file as
get-data.php
. Now, open your web-browser and check if everything is working correctly. Go to http://localhost/fcdemo/get-data.php?year=2010.
You should see XML data similar to this:
- <chart caption="Monthly New Users for the Year: 2010" xAxisName="Months" yAxisName="Users" showNames="1" bgColor="E6E6E6,F0F0F0" bgAlpha="100,50" bgRatio="50,100" bgAngle="270" showBorder="1" borderColor="AAAAAA" baseFontSize="12">
- <set value="486" name="Jan" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=1"/>
- <set value="443" name="Feb" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=2"/>
- <set value="553" name="Mar" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=3"/>
- <set value="550" name="Apr" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=4"/>
- <set value="634" name="May" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=5"/>
- <set value="622" name="Jun" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=6"/>
- <set value="710" name="Jul" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=7"/>
- <set value="772" name="Aug" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=8"/>
- <set value="850" name="Sep" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=9"/>
- <set value="1044" name="Oct" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=10"/>
- <set value="1175" name="Nov" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=11"/>
- <set value="761" name="Dec" link="newchart-xmlurl-get-data.php?type=daily&year=2010&month=12"/>
- </chart>
Test it out
Now that we have modified it, let's test out what we have created. Open your web browser and go tohttp://localhost/fcdemo/demo.html.
If you have followed the steps above correctly, you will see a working Column3D chart. When any of the monthly bars is clicked, the chart will transition to a daily chart for selected month. Subsequently, the same applies to the days as well.
A nifty added feature is that you can use the back button of your browser to return to the previous chart.
The Result
Here is a video which details how our completed application should look:
Conclusion: Extend & Experminent
If you followed this tutorial all the way through, you should now have a decent understanding of what it takes to create a simple LinkedCharts web application with PHP/MySQL. Similar charts and dashboards can be made for:
- How many products sold over a period of time?
- How many times your website went down?
- How many times a particular web page was accessed?
The basic structure is the same for each of these scenarious: have a
Time
field in your table, and use that data to build the XML. Finally, fetch this XML to the chart.
Take a look at some of these stunning dashboard demos for more inspiration. Thank you for reading, and, if you have any questions or comments about this tutorial, please post!