Introduction

This idea was born from my need of handling (insert and show) a set of data almost from everywhere.

The first attempt I made was using an OpenOffice spreadsheet, shared via a free sharing service such as DropBox (sharing is actually useless since the only user was myself: I just needed a central place to retrieve and save these data).

Very soon I realized that this wasn’t working for several reasons:

  1. plotting capabilities of OpenOffice seemed poor when dealing with moderate/big quantities of data ( > 500 records)
  2. whenever I needed to see/edit the data I needed an internet enabled computer with OpenOffice installed; requirement may be lowered by exporting an image from the spreadsheet plot and inserting it in some static html page but I would have been forced to keep this image in sync with the data every time I changed them.

Then, someone suggested me to build a small web application to add new data and show them, I would only need an internet connection to do my job.

I also realized that advantages are several:

  1. no more need of using OpenOffice
  2. can view/add data from a mobile device
  3. great freedom data visualization

So I started working at this php web app and this is the result of my efforts.

The application at a glance

I built a single html page containing:

  1. an html form for data upload (data are written to a csv file)
  2. data plots using a custom php script that loads data and uses an external charting library to show them.

This is an image of the whole process:

When the web page is loaded, the form is shown and a first plot is built with existing data; then, when data are submitted, the page is reloaded and plots are updated.

The external charting library

At a first time I had a look at the famous GD library and soon I realized that I wanted some higher level library because I did not want to create it by myself.

After some searching I found three candidates:

  1. Libchart
  2. pChart
  3. jpGraph

The first two libraries seemed more suitable since they are free and extremely simple to be used, the third one, instead, has a more complex usage and has a “Professional” version (for commercial usage).

At the beginning I thought I could use one of the first two, because they produced better looking plots with fewer lines of code; but then I switched to jpGraph because it is more flexible, expecially in handling abscissa ticks and lables without showing them crowded.

These first attempts had a nice side-effect since forced me to use a better application design, isolating graphics and I/O code from the remainder.

Implementation

These are the main application elements:

  1. a single web page containing form and plots
  2. a form “target” php file
  3. a php file handling I/O
  4. a php file that builds the plots using jpGraph and input data

let’s describe them one by one:

The web page

This is a “regular” web page with a simple stylesheet, some JavaScript, the form and some php logic.

It’s important parts are:

  1. php declarations of URI and URL of various files. Note: paths are needed in case page and other php files reside in different folders; this can be useful to add the app to a CMS, see below.
    URL are needed by html code, e.g.:

    1. <img src=‘<?php echo $imageFileURL ?>’ />

    URI are needed by php for accessing various files (data, plot images):

    1. if ( file_exists($dataFileURI) )
  2. HTML form: along with the data fields, I added a “password” field that reasonably would be present in a “mature” application. Also, there are some hidden params to be passed to php routine: the data filename and the return address for the php form target (see below in the next item).
  3. JavaScript is used to perform data validation and to retrieve the page URL for the return address. Again, this is done for CMS integration. For the same reason JavaScript code is inlined in the html body (when publishing on a CMS you do not have access to html head).
  4. PHP code invokes graphics wrapper that uses jpGraph. All three libraries support on the fly creation of images but I decided to create files to introduce an optimization, plot is rebuilt only if data are newer that images:
    1.  
    2. // optimization: if csv file is older than image do not rebuild them
    3. if ( (file_exists($imageFileURI) &amp;&amp; filemtime($imageFileURI) < filemtime($dataFileURI)) || !file_exists($imageFileURI))
    4. {
    5.  

    So this part is very simple, if data exists and are newer than images read them and rebuild the plots images:

    1.  
    2. read($dataFileURI, $xvalues, $yvalues1, $yvalues2, $yvalues3, $comments);
    3. buildPlotImage($imageFileURI, $xvalues, $yvalues1, $yvalues2, $yvalues3, $comments);
    4.  
    5. $xvaluesS = array_slice($xvalues, count($xvalues)-100);
    6. $yvalues1S = array_slice($yvalues1, count($xvalues)-100);
    7. $yvalues2S = array_slice($yvalues2, count($xvalues)-100);
    8. $yvalues3S = array_slice($yvalues3, count($xvalues)-100);
    9. buildPlotImage($imageTailFileURI, $xvaluesS, $yvalues1S, $yvalues2S, $yvalues3S, $comments);
    10.  

    Note:

    1. I’m creating two plots: the latter shows only data “tail” using last 100 records (this value is arbitrary)
    2. (I know, I’m lazy and I do not want to change this part) textual comments are passed as params too, even if they are not used
    3. plot routines need file URI, i.e. related to server internal filesystem
  5. Finally, two plots are shown:

    1.  
    2. if ($dataExists)
    3. {
    4. ?>
    5. <div style="text-align: center;">
    6. <h2>Output – complete set</h2>
    7. <img src="<?php echo $imageFileURL ?>" alt="" />
    8.  
    9. <img src="<?php echo $imageTailFileURL ?>" alt="" /></div>
    10. <?php
    11. }
    12. else
    13. {
    14. ?>
    15. <h2>Output – no data</h2>
    16.  

    this part is in case data are missing.

Form php target

This script simply passes data to I/O scripts. I could have written data to file directly but I wanted to add a little structure to the app separating I/O code. Data are retrieved from POST params, time is added in this phase, before sending data to I/O scripts. jpGraph library supports time in abscissa values almost automagically simply using them in the form of POSIX time().

I/O scripts

Nothing special, here: a function to write a record (time, three data, textual description) and a second to read all data from file.

Drawing scripts

jpGraph calls on csv data build the plot. As I wrote, jpGraph is quite complex but has a good documentation and several examples. In order to use TrueType fonts I added them to app folder to avoid the hassles of finding it on the server or implementing workarounds in case they’re missing. This is how tell jpGraph where fonts are:

  1. DEFINE("TTF_DIR","fonts/");

WordPress integration

These are the steps that where necessary in order to use the app inside WordPress, I guess most of them hold for other CMS too:

  1. paths: php scripts, data files and images cannot reside in the same folder of the page content (which actually … does not exists since content is on a database)
  2. return address: it must be discovered dynamically for the same reason (no static page).
  3. JavaScript code cannot be placed in the header: when adding a content to WordPress you are changing a part which is inside the html body. So JavaScript goes inline.
  4. To add php and Javascript code to a WP page I had to install the “Text Control” plugin and force WP to skip every interpretation of content

Here’s the result!

An example page is (mine is outside the CMS) here; I’m automatically filling the field that handles the password/authorization code (see above).

The complete source code (for a static web page) is : OnlinePlotExample.

You have to download the jpGraph library by yourself (it’s too big to be uploaded to the server) from here and put it in the “php” folder.

Future: wishes and improvements

This small app could be improved in countless ways, in particular design must be improved, e.g. removing all those php/html mixes and wrapping all php code inside a class.

Also, I guess a web app should perform a sort of installation to let the user choose:

  1. data filename and folder
  2. own password for adding new data
  3. the wanted number of series for each record
  4. custom abscissa values
  5. data validity ranges for data validation and for plotting (e.g. min and max plot values)

in this way I could also be possible to provide multi-user plotting capabilities.

Share

One Response to “Plot your data using php”

Leave a Reply

You must be logged in to post a comment.