PHP + MySQL + HighCharts: Mostrar gráfica dinámica en función del tiempo

Hola Geeks!, en este nuevo e interesante tutorial vamos a aprender a usar la librería HighCharts y con ayuda de PHP y MySQL vamos a mostrar un valor aleatorio en función del tiempo. El objetivo del tutorial será por una parte crear una aplicación que inserte datos aleatorios en la base de datos y por otra parte muestre estos datos en una gráfica generada con Highcharts.

En primer lugar, vamos a crear una base de datos llamada geekytheorybd con una tabla llamada "random" que contendrá tres campos, el primer campo será el id con valor autoincrementable, el segundo campo "valor" contendrá los número aleatorios insertados y el tercer y último campo almacenará el tiempo.

Si no sabes cómo crear una base de datos puedes consultar el siguiente tutorial: JAVA - PHP -MySQL: Creación de una base de datos en MySQL.

Una captura de la base de datos que vamos a usar es la siguiente:

Podemos resaltar que el campo de tiempo es de tipo TIMESTAMP y que como valor predeterminado va a tener un valor CURRENT_TIMESTAMP, esto quiere decir que cuando insertemos cualquier valor en la base de datos y en el caso de que no introduzcamos un valor en el campo "tiempo" se almacenará la hora actual.

El siguiente paso será crearnos un fichero llamado RandomClass.php donde escribiremos una clase para gestionar la tabla "random" de nuestra base de datos. Esta clase va a tener cinco funciones básicas:

  • function conectarBD()
  • function desconectarBD($conexion)
  • function getArraySQL($sql)
  • function insertRandom()
  • function getAllInfo()

Podemos observar el contenido del fichero RandomClass.php en el siguiente párrafo, el código esta comentado y se entiende claramente su función:

<?php class RandomTable{ public $IDr = 0 ; //Función que crea y devuelve un objeto de conexión a la base de datos y chequea el estado de la misma. function conectarBD(){ $server = "localhost"; $usuario = "root"; $pass = ""; $BD = "GeekyTheoryBD"; //variable que guarda la conexión de la base de datos $conexion = mysqli_connect($server, $usuario, $pass, $BD); //Comprobamos si la conexión ha tenido exito if(!$conexion){ echo 'Ha sucedido un error inexperado en la conexion de la base de datos<br>'; } //devolvemos el objeto de conexión para usarlo en las consultas return $conexion; } /*Desconectar la conexion a la base de datos*/ function desconectarBD($conexion){ //Cierra la conexión y guarda el estado de la operación en una variable $close = mysqli_close($conexion); //Comprobamos si se ha cerrado la conexión correctamente if(!$close){ echo 'Ha sucedido un error inexperado en la desconexion de la base de datos<br>'; } //devuelve el estado del cierre de conexión return $close; } //Devuelve un array multidimensional con el resultado de la consulta function getArraySQL($sql){ //Creamos la conexión $conexion = $this->conectarBD(); //generamos la consulta if(!$result = mysqli_query($conexion, $sql)) die(); $rawdata = array(); //guardamos en un array multidimensional todos los datos de la consulta $i=0; while($row = mysqli_fetch_array($result)) { //guardamos en rawdata todos los vectores/filas que nos devuelve la consulta $rawdata[$i] = $row; $i++; } //Cerramos la base de datos $this->desconectarBD($conexion); //devolvemos rawdata return $rawdata; } //inserta en la base de datos un nuevo registro en la tabla usuarios function insertRandom(){ //Generamos un número entero aleatorio entre 0 y 100 $ran = rand(0, 100); //creamos la conexión $conexion = $this->conectarBD(); //Escribimos la sentencia sql necesaria respetando los tipos de datos $sql = "insert into random (valor) values (".$ran.")"; //hacemos la consulta y la comprobamos $consulta = mysqli_query($conexion,$sql); if(!$consulta){ echo "No se ha podido insertar en la base de datos<br><br>".mysqli_error($conexion); } //Desconectamos la base de datos $this->desconectarBD($conexion); //devolvemos el resultado de la consulta (true o false) return $consulta; } function getAllInfo(){ //Creamos la consulta $sql = "SELECT * FROM random;"; //obtenemos el array con toda la información return $this->getArraySQL($sql); } } ?>

Una vez que tenemos la clase que introducirá valores aleatorios a nuestra base de datos, vamos a realizar un script que realiza los siguientes pasos:

  1. Insertar un valor aleatorio con ayuda de la clase creada en el paso anterior [función insertRandom]
  2. Lectura de todos los datos de la base de datos [función getAllInfo]
  3. Dibujar gráfica con Highcharts

Una vez hemos visto los pasos que hay que seguir vamos a crear un fichero llamado drawChart.php que gestione estos pasos. En primer lugar incluimos el fichero RandomClass.php en esta clase e insertaremos un valor aleatorio en la base de datos:

<?php require_once("RandomClass.php"); //Creamos un objeto de la clase randomTable $rand = new RandomTable(); //insertamos un valor aleatorio $rand->insertRandom(); ?> Seguidamente obtenemos todos los datos de la tabla "random": $rawdata = $rand->getAllInfo();

A continuación tenemos que convertir el formato de fecha que recibimos de mysql en Timestamp, para ello usamos la función getTimestamp() de la clase Date. En un bucle for iremos obteniendo el valor del campo "tiempo" y del campo "valor" de la tabla "random", además, se obtendrá el TIMESTAMP del campo "tiempo". Una vez que tengamos esto, almacenaremos la información en dos arrays $valoresArray y $timeArray.

//nos creamos dos arrays para almacenar el tiempo y el valor numérico $valoresArray; $timeArray; //en un bucle for obtenemos en cada iteración el valor númerico y //el TIMESTAMP del tiempo y lo almacenamos en los arrays for($i = 0 ;$i<count($rawdata);$i++){ $valoresArray[$i]= $rawdata[$i][1]; //OBTENEMOS EL TIMESTAMP $time= $rawdata[$i][2]; $date = new DateTime($time); //ALMACENAMOS EL TIMESTAMP EN EL ARRAY $timeArray[$i] = $date->getTimestamp()*1000; }

Una vez que tengamos esto vamos a pasar a la parte "gorda" del tutorial que es la de dibujar una gráfica con la librería highcharts. En primero lugar vamos a incluir las librerías de highcharts en nuestro archivo:

<script src="https://code.jquery.com/jquery.js"></script> <!-- Importo el archivo Javascript de Highcharts directamente desde su servidor --> <script src="http://code.highcharts.com/stock/highstock.js"></script> <script src="http://code.highcharts.com/modules/exporting.js"></script>

Seguidamente vamos a crear un div en el que se insertará nuestra gráfica, este div debe tener un id para identificarlo:

<div id="contenedor"></div>

Por último vamos a añadir una función en javascript usando las funciones de la librería highcharts pero con el truco de que los datos que insertaremos en la gráfica serán los datos que hemos obtenido de la base de datos. Esta función es un ejemplo que vamos a usar nosotros, pero debemos de tener en cuenta de que con highcharts se pueden crear gran variedad de gráficas.

<script> chartCPU = new Highcharts.StockChart({ chart: { renderTo: 'contenedor' //defaultSeriesType: 'spline' }, rangeSelector : { enabled: false }, title: { text: 'Gráfica' }, xAxis: { type: 'datetime' //tickPixelInterval: 150, //maxZoom: 20 * 1000 }, yAxis: { minPadding: 0.2, maxPadding: 0.2, title: { text: 'Valores', margin: 10 } }, series: [{ name: 'Valor', data: (function() { // generate an array of random data var data = []; <?php for($i = 0 ;$i<count($rawdata);$i++){ ?> data.push([<?php echo $timeArray[$i];?>,<?php echo $valoresArray[$i];?>]); <?php } ?> return data; })() }], credits: { enabled: false } }); </script>

Podemos observar que en la etiqueta series tenemos un campo llamado data, dentro de este campo creamos una función que se llame al inicio del script, esta función añadirá parámetros a la gráfica, de tal forma que añadirá tantos parámetros como datos tenga la tabla "random".

A continuación podemos observar una captura de lo que genera el script:

Por último os dejo todo el código seguido, para los más perezosos xD:

RandomClass.php

<?php class RandomTable{ public $IDr = 0 ; //Función que crea y devuelve un objeto de conexión a la base de datos y chequea el estado de la misma. function conectarBD(){ $server = "localhost"; $usuario = "root"; $pass = ""; $BD = "GeekyTheoryBD"; //variable que guarda la conexión de la base de datos $conexion = mysqli_connect($server, $usuario, $pass, $BD); //Comprobamos si la conexión ha tenido exito if(!$conexion){ echo 'Ha sucedido un error inexperado en la conexion de la base de datos<br>'; } //devolvemos el objeto de conexión para usarlo en las consultas return $conexion; } /*Desconectar la conexion a la base de datos*/ function desconectarBD($conexion){ //Cierra la conexión y guarda el estado de la operación en una variable $close = mysqli_close($conexion); //Comprobamos si se ha cerrado la conexión correctamente if(!$close){ echo 'Ha sucedido un error inexperado en la desconexion de la base de datos<br>'; } //devuelve el estado del cierre de conexión return $close; } //Devuelve un array multidimensional con el resultado de la consulta function getArraySQL($sql){ //Creamos la conexión $conexion = $this->conectarBD(); //generamos la consulta if(!$result = mysqli_query($conexion, $sql)) die(); $rawdata = array(); //guardamos en un array multidimensional todos los datos de la consulta $i=0; while($row = mysqli_fetch_array($result)) { //guardamos en rawdata todos los vectores/filas que nos devuelve la consulta $rawdata[$i] = $row; $i++; } //Cerramos la base de datos $this->desconectarBD($conexion); //devolvemos rawdata return $rawdata; } //inserta en la base de datos un nuevo registro en la tabla usuarios function insertRandom(){ //Generamos un número entero aleatorio entre 0 y 100 $ran = rand(0, 100); //creamos la conexión $conexion = $this->conectarBD(); //Escribimos la sentencia sql necesaria respetando los tipos de datos $sql = "insert into random (valor) values (".$ran.")"; //hacemos la consulta y la comprobamos $consulta = mysqli_query($conexion,$sql); if(!$consulta){ echo "No se ha podido insertar en la base de datos<br><br>".mysqli_error($conexion); } //Desconectamos la base de datos $this->desconectarBD($conexion); //devolvemos el resultado de la consulta (true o false) return $consulta; } function getAllInfo(){ //Creamos la consulta $sql = "SELECT * FROM random;"; //obtenemos el array con toda la información return $this->getArraySQL($sql); } } ?>

drawchart.php

<HTML> <BODY> <meta charset="utf-8"> <?php require_once("RandomClass.php"); //Creamos un objeto de la clase randomTable $rand = new RandomTable(); //insertamos un valor aleatorio $rand->insertRandom(); //obtenemos toda la información de la tabla random $rawdata = $rand->getAllInfo(); //nos creamos dos arrays para almacenar el tiempo y el valor numérico $valoresArray; $timeArray; //en un bucle for obtenemos en cada iteración el valor númerico y //el TIMESTAMP del tiempo y lo almacenamos en los arrays for($i = 0 ;$i<count($rawdata);$i++){ $valoresArray[$i]= $rawdata[$i][1]; //OBTENEMOS EL TIMESTAMP $time= $rawdata[$i][2]; $date = new DateTime($time); //ALMACENAMOS EL TIMESTAMP EN EL ARRAY $timeArray[$i] = $date->getTimestamp()*1000; } ?> <div id="contenedor"></div> <script src="https://code.jquery.com/jquery.js"></script> <!-- Importo el archivo Javascript de Highcharts directamente desde su servidor --> <script src="http://code.highcharts.com/stock/highstock.js"></script> <script src="http://code.highcharts.com/modules/exporting.js"></script> <script> chartCPU = new Highcharts.StockChart({ chart: { renderTo: 'contenedor' //defaultSeriesType: 'spline' }, rangeSelector : { enabled: false }, title: { text: 'Gráfica' }, xAxis: { type: 'datetime' //tickPixelInterval: 150, //maxZoom: 20 * 1000 }, yAxis: { minPadding: 0.2, maxPadding: 0.2, title: { text: 'Valores', margin: 10 } }, series: [{ name: 'valor', data: (function() { // generate an array of random data var data = []; <?php for($i = 0 ;$i<count($rawdata);$i++){ ?> data.push([<?php echo $timeArray[$i];?>,<?php echo $valoresArray[$i];?>]); <?php } ?> return data; })() }], credits: { enabled: false } }); </script> </BODY> </html>

Y esto es todo si tenéis alguna duda comentar en el mismo post y por favor, compartir este tutorial en vuestras redes sociales.

¡Un saludo! @alex_esquiva

Podéis descargar el código en el siguiente repositorio de github.