Charts

Line Charts

Here is an extra section I added online after the PHP Black Book was printed.

You can draw line charts with PHP and basic HTML. The example can be refined using GIF, JPEG or PNG files. This version is slow to display in Netscape and some other browsers but can be tuned. A version built with more sophisticated code would display faster in problem browsers and would be a step toward using a higher resolution.

Data

First you need data. The following code simple converts a string to numbers in an array using ord(). $data contains a string of characters, the for() loop steps through the characters, ord() returns the binary integer value of each character, and the integer is stored in $numbers.

$data = "The quick brown fox jumped!";
$data_length = strlen($data);
for($i = 0; $i < $data_length; $i++)
   {
   $numbers[] = ord(substr($data, $i, 1));
   }

Display the contents of the number array using implode(). implode() connects all the values in an array using the string specified as the first parameter.

print(implode(", ", $numbers));

The code produces:

84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 32, 106, 117, 109, 112, 101, 100, 33

Chart Function

This is the function to produce the chart. Skip the code, look at the result, then read the code explanation.

function linearchart($data, $colour="blue", $origin=0, $increments=20)
   {
   $maximum_value = 0;
   foreach($data as $value)
      {
      if($value > $maximum_value)
         {
         $maximum_value = $value;
         }
      }
   $increment = $maximum_value / $increments;
   $percent = intval(90 / $increments); // 90% of the chart is available.
   // $origin is not yet implemented.
   $edge_line = '<td bgcolor="Black" width="1%">&nbsp;</td>';
   $rows = '<tr><td width="4%"><em>Item&nbsp;</em></td>' . $edge_line;
   for($i = 1; $i <= $increments; $i++)
      {
      $rows .= '<td bgcolor="Black" width="1%">&nbsp;</td>';
      }
   $rows .= '<td width="5%"><em>&nbsp;Value</em></td></tr>' . "\n";
   $separator_repeat = 10;
   $separator = '<tr><td>&nbsp;</td>' . $edge_line;
   for($i = 1; $i <= $increments; $i++)
      {
      $separator .= '<td bgcolor="Black" width="' . $percent . '">&nbsp;</td>';
      }
   $separator .= '<td>&nbsp;</td></tr>' . "\n";
   foreach($data as $key >= $value)
      {
      if($key > 0 and ($key % $separator_repeat) == 0)
         {
         $rows .= '';
         $rows .= $separator;
         }
      $rows .= '';
      $rows .= '<tr><td>' . $key . '&nbsp;</td>' . $edge_line;
      $x = $value / $increment;
      for($i = 1; $i <= $x; $i++)
         {
         $rows .= '<td bgcolor="blue" width="' . $percent . '">&nbsp;</td>';
         }
      for($i = $i; $i <= $increments; $i++)
         {
         $rows .= '<td>&nbsp;</td>';
         }
      $rows .= '<td width="' . $percent . '">&nbsp;' . $value . '</td></tr>' . "\n";
      }
   if(($key % $separator_repeat) != 0)
      {
      $rows .= $separator;
      }
   return('<table border="0" cellspacing="0" cellpadding="0">' . "\n"
      . $rows . "</table>\n");
   }

Chart Display

Here is a chart built with HTML and no graphics. You can convert this chart to higher resolution by replacing the character elements with pixel size files of type GIF, JPEG, or PNG.

print(linearchart($numbers));

The code produces:

Item                                             Value
                                           84
                                           104
                                           101
                                           32
                                           113
                                           117
                                           105
                                           99
                                           107
                                           32
                                             
10                                             98
11                                             114
12                                             111
13                                             119
14                                             110
15                                             32
16                                             102
17                                             111
18                                             120
19                                             32
                                             
20                                             106
21                                             117
22                                             109
23                                             112
24                                             101
25                                             100
26                                             33
                                             

The Code Explained

Here is a chart built with HTML and no graphics. You can convert this chart to higher resolution by replacing the character elements with pixel size files of type GIF, JPEG, or PNG.

The code is implemented as a function so you can change things within the function without worrying about variable names. If the function became more complicated or the chart generation process required more functions, you would be better off looking at defining a class and generating an object.

Note the variables passed to the chart function. $data receives an array of values for display. Each array entry supplies a value for one line in the chart and the value is displayed on the right to let people easily see the exact values. The entry keys are displayed on the left and could be used for time, date, or any value that continually changes. If you need to display data that could have duplicate keys, you would change the array to have both values as part of the entry and let the key default to a system generated vlaue.

$colour provides the name of the colour for the value bars and can contain #RGB numbers. $origin is not yet implemented but could let you start a value bar from a value other than zero. If you look at the example, there are no values under 32 so so you could increase the resolution of this chart by starting the chart at 32 on the left hand side. $increments supplies the number of line size increments included in the chart. When I tested this script with Netscape, twice as many lines, and twice as many increments, the display was noticeably slow. At four times as many llines and 100 increments, Netscape 4.78 choked.

function linearchart($data, $colour= 'blue', ;$origin=0, $increments=20)
   {

The next code loops through the input data to find the largest value so the chart increments can be calculated. If you are collecting many charts run on separate days or months, you will find some charts easier to follow if they are set to the same fixed maximum value. You can more easily perform a quick visual comparison of charts when their size and layout are the same.

   $maximum_value = 0;
   foreach($data as $value)
      {
      if($value > $maximum_value)
         {
         $maximum_value = $value;
         }
      }

$increment and $percent are used to space out the blue bars on the chart. $increment is vidided in to values to decide how many increments will be blue. $percent is the percentage value supplied in the HTML for the columns containing increments.

   $increment = $maximum_value / $increments;
   $percent = intval(90 / $increments); // 90% of the chart is available.

The following code creates the first line or row of the chart. You can add any headings you line in this cpde as it is performed just once per chart.

   $rows = '<tr><td width="4%"><em>Item&nbsp;</em></td>' . $edge_line;
   for($i = 1; $i <= $increments; $i++)
      {
      $rows .= '<td bgcolor="Black" width="1%">&nbsp;</td>';
      }
   $rows .= '<td width="5%"><em>&nbsp;Value</em></td></tr>' . "\n";

The separator code adds an extra line at regular intervals to help you line up keys and values on charts that have very few full rows. You can leave the separators out when your charts has lots of lines running most of the way toward the value column.

   $separator_repeat = 10;
   $separator = '<tr><td>&nbsp;</td>' . $edge_line;
   for($i = 1; $i <= $increments; $i++)
    {
    $separator .= '<td bgcolor="Black" width="' . $percent . '">&nbsp;</td>';
    }
   $separator .= '<td>&nbsp;</td></tr>' . "\n";

The big foreach() loop steps through the value array using the new foreach() funtion in PHP. If your version of PHP does not contain foreach() and you cannot update, use the while(list($key, $value) = each($data)) structure shown in the PHP Black Book.

   foreach($data as $key >= $value)
      {