Javascript – How to continuously update a PHP variable without refreshing a page

ajaxjavascriptjqueryphp

I'm making a website that shows data from a MySQL database in Morris graphs. Basically I have a database that gets new measurements every minute, and I'm trying to show these changes live without having to reload the whole page. I have shortened my code for this question, but here's basically what I have:

PHP code:

<?php
   while($measurement = mysqli_fetch_array($result)){
       $data += $measurement['data'];
   }
?>

And the script:

function data() {
        var ret = [];
        ret.push({
          y: 'Today',
          a: <?php echo $data; ?>
        });
      return ret;
    }

var graph = Morris.Bar({
        element: 'graph',
        data: data(),
        xkey: 'y',
        ykeys: ['a'],
        labels: ['random label']
    });

function update() {
      graph.setData(data());
    }

setInterval(update, 60000);

The graph is then shown in a div with the id "graph". So the problem is that the update function doesn't update the graph with new data as $data doesn't get updated. I've heard that I can somehow create a PHP function and continuously run that using Ajax and have it update my $data variable, but I have no idea how to do that.

In order for the graph to update I have to reload the whole page, and this works fine using a meta tag that resfreshes the page every 60 seconds, but it seems like a bad solution.

I have also tried to put the code in a separate PHP file and run that using this code:

var auto_updater = setInterval(
    (function () {
        $("#graph").load("data.php");
    }), 60000);

This also works fine, but the problem is that it redraws the whole graph and that causes the scroll bar on my site to go crazy. What I want is to update the data variable in Morris.Bar, not the whole thing. Any help would be appreciated.

Best Solution

Edit: because you only ever need one value, your json will only be that value. Though technically that does not make for valid json (there should be an object at the top level) it works with jquery just fine.

PHP: (data.php)

<?php
  $data = // obtain current value of data from somewhere
  echo $data; // should be an integer
?>

JS:

$(document).ready( function () {
  var data = []; // data is empty
  var graph = Morris.Bar({
    element: 'graph',
    data: data
    labels: ['random label']
  });

  function update () {
    $.getJSON( "data.php", function (newv) {
      data.push( { x: newv, y: "Today" } ); // store new value
      graph.setData( data );                // update the graph
    });
  }

  update();
  setInterval( update, 1000 );
});

and that's everything to it!


It is impossible to "keep PHP running in the background" or something like that, your attempt is correct. However instead of loading new HTML you should load the pure data (for example as a JSON document) and then push that data into your existing dataset via JS. Using JS to grab updated data from the server is accomplished with AJAX.

You could for example use $.getJSON

Edit: The full JS would look like this:

var initial_data = <?php echo $data; ?> // or leave this out and replace with another $.getJSON for clean code!
$(document).ready( function () {
  var graph = Morris.Bar( ... );

  setInterval( function () {
    $.getJSON( "data.php", function (data) {
      graph.setData( data );
    });
  }, 1000 );
});

and the response from PHP should look something like this:

[
  { "x": 10, "y": 20 },
  { "x": 3, "y": 12 },
  { "x": 8, "y": 19 }
]

so the PHP would look like this maybe:

[
  <?php
    // first one seperately because it can't have a leading comma - JSON is strict
    $measurement = mysqli_fetch_array($result)
    echo '{ "x": ' . $result["data"]["x"] . ', "y": ' . $result["data"]["x"] . ' }';
    while($measurement = mysqli_fetch_array($result)) {
     // no idea what data looks like, I'm assuming it has x and y properties
     echo ', { "x": ' . $result["data"]["x"] . ', "y": ' . $result["data"]["x"] . ' }';
    }
  ?>
]