Home > php > Embed JpGraph in web pages

Embed JpGraph in web pages

Problem

In PHP, you use JpGraph to produce graphs. You would like to include (embed) such a graph in a web page but you get the following error: “The image cannot be displayed, because it contains errors.

Explanation

Let’s see the following basic example (example0.php):

<?php // content="text/plain; charset=utf-8"
require_once ('lib/jpgraph/src/jpgraph.php');
require_once ('lib/jpgraph/src/jpgraph_line.php');

// Some data
$ydata = array(11,3,8,12,5,1,9,13,5,7);

// Create the graph. These two calls are always required
$graph = new Graph(350,250);
$graph->SetScale('textlin');

// Create the linear plot
$lineplot=new LinePlot($ydata);
$lineplot->SetColor('blue');

// Add the plot to the graph
$graph->Add($lineplot);

// Display the graph
$graph->Stroke();
?>

Actually, this code will produce a PNG file, thus it will set the header to ‘Content-type: image/png‘. Once the header is set, it cannot be changed. Now let’s see what happens if you try to mix it with HTML:

<p>
Beginning of the HTML page. Normal text.
</p>
<?php
   // the previous code of example0.php, I won't repeat that
?>

Since the page starts with normal HTML, the header will be set to ‘Content-type: text/html‘. Then the JpGraph PHP block will try to set ‘Content-type: image/png‘, so there is a conflict.

Solution #1

The easy way is to make a PHP file that produces a graph and include this file as if it were a normal image:

<p>
This is normal HTML text.
</p>
<img src="example0.php">

What happens if you want to pass some data to the JpGraph PHP file, regarding how to produce the graph? If the data are simple, you could pass them via GET parameters:

This is normal HTML text.
<img src="example0.php?label1=...&label2=...&data1=...&data2=...">

However, if the data is complicated, it would be better to include JpGraph directly in your PHP. This way, JpGraph has access to the necessary data structures from which it can construct the graph. I will explain it in the next section.

Solution #2

Let’s see how to include JpGraph directly in our PHP script:

<p>
Normal HTML at the beginning of the page.
</p>
<?php
   // produce $ydata ...
?>
<?php
   define('PREFIX_DIR', 'tmp.jpgraph');   // images will be created here
   define('PREFIX', 'jpgraph');   // prefix for the images, can be anything
   define('TIME_LIMIT', 3 * 60);    // 3 minutes
   $tmpfname = tempnam(PREFIX_DIR, PREFIX);   // create temp filename
?>
<?php // content="text/plain; charset=utf-8"
require_once ('lib/jpgraph/src/jpgraph.php');
require_once ('lib/jpgraph/src/jpgraph_line.php');

// Some data
$ydata = array(11,3,8,12,5,1,9,13,5,7);

// Create the graph. These two calls are always required
$graph = new Graph(350,250);
$graph->SetScale('textlin');

// Create the linear plot
$lineplot=new LinePlot($ydata);
$lineplot->SetColor('blue');

// Add the plot to the graph
$graph->Add($lineplot);

// Display the graph
$graph->Stroke($tmpfname);
clean_old_tmp_files();
?>
<?php
   ?><img src="<?php echo get_relative_path($tmpfname); ?>"><?php
   #unlink($tmpfname);   // wouldn't work correctly
?>
<?php
   function get_relative_path($filename) {
      return preg_replace("/^.*\/(".PREFIX_DIR."\/.*)/", "$1", $filename);
   }

   function clean_old_tmp_files()
   {
      foreach (glob(PREFIX_DIR.'/'.PREFIX."*") as $filename)
      {
         #printf ( "Name: %s; age: %d<br>\n", $filename, time() - filemtime($filename) );

         $age = time() - filemtime($filename);
         if ($age > TIME_LIMIT) {
            unlink($filename);
         }
      }
   }
?>

As you can see, at the beginning of the page we show some HTML text that is followed by the graph. The data of the graph is produced by our PHP, and JpGraph’s PHP has direct access to it, thus no parameter passing is necessary.

The idea is the following: the graph is written to the file system. Then, this file is shown using the <img src="..."> tag. A time limit is set (here 3 minutes). When the script is called again, it’ll automatically remove images that are older than the limit.

Unfortunately, the image cannot be deleted right after the <img src="..."> tag. When your browser sees this tag, it’ll launch a thread to fetch the image and steps on. That is, the image would be deleted immediately after the creation, and the browser couldn’t show it. So the image file must be left there. My solution is to set a time limit, and when the PHP page is called again, it’ll remove the old images. This way you’ll always have some temporary images in the temp folder, but not many.

Preparation:

I suppose you have your PHP script in your ~/public_html directory. Here create a temporary directory for the images called tmp.jpgraph and set its permission to 777 (chmod 777 tmp.jpgraph).

Advertisements
Categories: php Tags:
  1. viraj
    February 15, 2011 at 07:59

    Hi, I have to generate gantt chart with jpgraph which works fine. The problem comes when i try to add a hyperlink on the bar.

    $bar-> SetCSIMTarget($alt_url, $alt_text);
    $bar-> title-> SetCSIMTarget($alt_url, $alt_text);

    I can’t click on the bar as there is a style on the image(zoom in and out). How can i disable the zooming? And make the bar clickable?

    Some help would be greatly appreciated.

  2. Bob
    October 2, 2011 at 15:13

    Does this work? I don’t see any image when I run the code.

  3. bob
    October 3, 2011 at 10:29

    How does this line work? Isn’t the “” within a quote? Seems like it would be treated just as text and not evaluated?

    <img src="”>

  4. bob
    October 3, 2011 at 10:35

    Oh OK I figured it out. I just did not have the correct paths to the jpgraph includes in my version.

    • Stendhal
      December 12, 2011 at 22:57

      Doesn’t work for me: It still says: Invalid argument supplied for foreach()…so $filename is not an array…isn’t it? I’m begginer with PHP, I don’t know what to do…Can anyone help, please?

  5. illiana
    December 15, 2011 at 04:12

    hi experts! im on my way to produce graph with php for my assignment. im having probs and this warning are:

    Warning: require_once(jpgraph/jpgraph.php) [function.require-once]: failed to open stream: No such file or directory in C:\Program Files\EasyPHP-5.3.6.1\www\PHP-Login1\example.php on line 2

    Fatal error: require_once() [function.require]: Failed opening required ‘jpgraph/jpgraph.php’ (include_path=’.;C:\php\pear’) in C:\Program Files\EasyPHP-5.3.6.1\www\PHP-Login1\example.php on line 2

    im sure i’d really include the jpgraph folder in a same directory. i have no idea how to solve this problems. perhaps, u dont mind to help me. thanks in advance.

    the scripts:

    SetScale('textlin');
     
    // Create the linear plot
    $lineplot=new LinePlot($ydata);
    $lineplot->SetColor('blue');
     
    // Add the plot to the graph
    $graph->Add($lineplot);
     
    // Display the graph
    $graph->Stroke();
    
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: