I am using google charts to display a line graph on my locally hosted web page. I am using mysqli to take the data from my phpmyadmin database then echoing this into the row spaces in the javascript.
This is the code within my html body:
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
<script>
google.charts.load('current', {packages: ['corechart', 'line']});
google.charts.setOnLoadCallback(drawBasic);
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Date');
data.addColumn('number', 'Speed');
data.addRows([
<?php
$sql = "SELECT id_rides, speed, date_completed FROM rides_done WHERE (id_users = $_SESSION[id])";
$result = mysqli_query($link, $sql);
while($row = mysqli_fetch_assoc($result)) {
$date = $row['date_completed'];
$speed = floatval($row['speed']);
echo "['".$date."', ".$speed."],";
}
?>
]);
var options = {
hAxis: {
title: 'Ride date'
},
vAxis: {
title: 'Average speed'
}
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
The problem is that nothing is being displayed on the web page.
I know that the query works as I tried this on it's own outside of the javascript and this was output: results of sql query
Before I added the dynamic element of the chart it was working fine with just random lists of data.
I was expecting to see a line graph with 'Average Speed' on the y-axis and 'Ride date' on the x-axis with 7 datapoints but nothing was displayed.
It seems that js is particular about datatypes here so I'm wondering if it is something to do with either of the following lines - both of which I have been fiddling around with to no avail.
echo "['".$date."', ".$speed."],";
data.addColumn('string', 'Date');
data.addColumn('number', 'Speed');
Thank you very much. All suggestions and ideas are very welcome. As is probably evident I am very new to Javascript so likely to be making some stupid mistakes.
A couple of things I would say: As you appear to wish to use a date within the dataTable perhaps setting that as a date type column would be better and casting the value from the db query as a date using new Date(str). I'd also suggest that you use json_encode once you have run the db query to create a JSON object rather than manually building a string as you do above - one downside to that approach is the trailing comma which might cause issues.
I rattle together a working demo using bogus data from my db to emulate what you were trying to do here. The SQL query uses aliases to take arbitrary data and name it as you do so the Javascript remains fairly much the same.
With the JSON data it is easy to iterate through the Object using Object.keys( json ).forEach() type structure ( I apologise if this is new to you )
<?php
#add a db connection
chdir('../../dbo');
require 'db-conn-details.php';
require 'mysqli-conn.php';
?>
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<script src='//www.gstatic.com/charts/loader.js'></script>
<script></script>
<title>Google charts.....</title>
<style>
#chart_div{
width:800px;height:600px
}
</style>
</head>
<body>
<div id='chart_div'></div>
<script>
<?php
$sql = 'SELECT `speed`, `date_completed` FROM `rides_done` WHERE ( `id_users` = $_SESSION[id] )';
$sql = 'select `dr` as `speed`, date(`lasteditdate`) as `date_completed` from `testtable` limit 20'; # example sql...
$result = $link->query( $sql );
$json = json_encode( $result->fetch_all( MYSQLI_ASSOC ) );
printf('const json=%s;', $json );
?>
google.charts.load('current', { packages: ['corechart'] } );
google.charts.setOnLoadCallback( drawBasic );
function drawBasic() {
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', 'Speed');
Object.keys( json ).forEach( key=>{
let obj=json[ key ];
data.addRow( [ new Date( obj.date_completed ), parseFloat( obj.speed ) ] );
})
var options = {
hAxis: {
title: 'Ride date'
},
vAxis: {
title: 'Average speed'
}
};
var chart = new google.visualization.LineChart( document.getElementById('chart_div') );
chart.draw( data, options );
}
</script>
</body>
</html>
The above yielded a chart like this:
Related
I have a PHP array of country names -
<?php
$countries_array = array("Russia", "Australia", "Chile");
?>
I need to show these countries on map via the Google Geochart map in Javascript and using this code -
function drawRegionsMap() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Country');
<?php
foreach ($countries_array as $cty) {
echo "data.addRow(['Country', " . $cty . "]);";
}
?>
var options = {backgroundColor: '#E7F2F4'};
var chart = new google.visualization.GeoChart(document.getElementById('regions_div'));
chart.draw(data, options);
}
I guess I'm passing the countries array in a wrong way, because the map doesn't show these countries.
How can I correct it ?
Note PHP serves $countries_array so you need to be within PHP script tags to output the array. It is probably easier to add each data using addRow(), it makes the syntax simpler.
function drawRegionsMap() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Country');
<?php
foreach ($countries_array as $cty) {
print "data.addRow(['" . $cty . "']);" . PHP_EOL;
}
?>
var options = {backgroundColor: '#cccccc'};
var chart = new google.visualization.GeoChart(document.getElementById('regions_div'));
chart.draw(data, options);
}
I have the following bit of code that draws graphs, in a loop, using google.visualisation based on values from a SQL table which I store in 3 arrays(i.e. $TotalView, $TotalFemaleView and $TotalMaleView) in the PHP portion. I use json_encode(referred this link) so I can use these arrays in JavaScript. But I am unable to access the array elements to draw the graphs. I have tried displaying the values of the arrays and they are correct.
<?php
$servername = "localhost";
$username = "root";
$password = "root123";
$dbname = "test";
$AdName=[];
$TotalView=[];
$TotalMaleView=[];
$TotalFemaleView=[];
$rowcount=0;
// Create connection
$con = mysqli_connect($servername, $username, $password, $dbname);
// Check connection
if ($con->connect_error) {
die("Connection failed: " . $con->connect_error);
}
$result=mysqli_query($con,"SELECT `Ad Name`,`Total View Count`, `Total Female Viewers`, `Total Male Viewers` FROM `addata` WHERE `Disp Id`=1");
$rowcount=mysqli_num_rows($result);
if(!$result) {
die('Could not get data: ' . mysql_error());
}
// output data of each row
for($x = 0; $x < $rowcount; $x++)
{
$row = $result->fetch_assoc();
$TotalView[$x]=$row["Total View Count"];
$TotalFemaleView[$x]=$row["Total Female Viewers"];
$TotalMaleView[$x]=$row["Total Male Viewers"];
$AdName[$x]=$row["Ad Name"];
}
$con->close();
?>
<html>
<body>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<ul id="stats"></ul>
<script type="text/javascript">
var array1 = <?php echo json_encode($TotalView);?>;
var array2 = <?php echo json_encode($TotalFemaleView);?>;
var array3 = <?php echo json_encode($TotalMaleView);?>;
var array4 = <?php echo json_encode($AdName);?>;
google.charts.load('current',
{ callback: function ()
{
for ( y = 0; y < <?php echo $rowcount ?>; y++)
{
var data = new google.visualization.DataTable();
data.addColumn('string', 'list');
data.addColumn('number', 'Viewers');
data.addRows([
['TotalViewers',array1[y]],
['Female Viewers', array2[y]],
['Male Viewers', array3[y]]
]);
var options = {title:array4[y],width:400,height:300};
var container = document.getElementById('stats').appendChild(document.createElement('div'));
var chart = new google.visualization.ColumnChart(container);
chart.draw(data, options);
}
},
packages: ['corechart']
});
</script>
</body>
</html>
Can anyone point me towards the right direction?
Based on the information in your comments and updated PHP code, it seems that your data returned from the database queries has numbers in the form of strings. Before using eval() or the Javascript Number object, if you looked in the browser console then you might have seen errors like this:
Uncaught Error: Type mismatch. Value 12 does not match type number in column index 1
There are multiple options to resolve this (without using eval()):
Type cast the values as an integer or float when adding to the output arrays in PHP
$TotalView[$x] = (float)$row["Total View Count"];
use the JSON_NUMERIC_CHECK flag with json_encode (see this answer for more info).
var array1 = <?php echo json_encode($TotalView, JSON_NUMERIC_CHECK );?>;
But beware there are drawbacks to using that constant (see this article for an example).
See this updated phpfiddle. As you can see, I created a class to simulate the database query (since I don't have a database connection in that sandbox) but allows to have the same array creation.
Please run that fiddle, and inspect the output in the browser console. Notice how the results of json_encode() produce valid arrays in Javascript, like:
var array1 = [12,10,6];
var array2 = [8,4,1];
var array3 = [4,6,5];
var array4 = ["Audi","BMW","Suzuki"];
Interestingly, the unordered list tag (i.e. <ul id="stats">), which is considered flow content, is added to the head tag in your sample code. The head tag only allows meta-data content. Move that unordered list tag to the body tag.
See the output demonstrated in the snippet below.
var array1 = [22, 16, 35, 11];
var array2 = [10, 3, 4, 9];
var array3 = [12, 13, 31, 2];
google.charts.load('current', {
callback: function() {
for (var y = 0; y < array1.length; y++) {
var data = new google.visualization.DataTable();
data.addColumn('string', 'list');
data.addColumn('number', 'Viewers');
data.addRows([
['TotalViewers', array1[y]],
['Female Viewers', array2[y]],
['Male Viewers', array3[y]]
]);
var options = {
title: 'Ad 1',
width: 400,
height: 300
};
var container = document.getElementById('stats').appendChild(document.createElement('div'));
var chart = new google.visualization.ColumnChart(container);
chart.draw(data, options);
}
},
packages: ['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<ul id="stats"></ul>
Okay, I solved it. Had to pass the arrays in the eval() function before using them in the google.visualization function.
google.charts.load('current',
{ callback: function ()
{
for ( y = 0; y < <?php echo $rowcount ?>; y++)
{
array1[y]=eval(array1[y]);
array2[y]=eval(array2[y]);
array3[y]=eval(array3[y]);
var data = new google.visualization.DataTable();
data.addColumn('string', 'list');
data.addColumn('number', 'Viewers');
data.addRows([
['TotalViewers',array1[y]],
['Female Viewers', array2[y]],
['Male Viewers', array3[y]]
]);
var options = {title:array4[y],width:400,height:300};
var container = document.getElementById('stats').appendChild(document.createElement('div'));
var chart = new google.visualization.ColumnChart(container);
chart.draw(data, options);
}
},
packages: ['corechart']
});
EDIT:
I found what was causing the problem and a better solution to the eval().
The json_encode was storing the elements as strings in the arrays(as you can see from my source here).
According to this, it is a PHP version specific problem and there are a couple of workarounds:
Adding the flag JSON_NUMERIC_CHECK to the json_encode function. So
in my case, it will be: var array1 = <?php echo json_encode($TotalView,JSON_NUMERIC_CHECK);?>. But this, according to some of the comments, is unreliable in certain cases.
Another solution is fixing it in the PHP section while reading the database elements from the database. $TotalView[$x]=(int)$row['Total View Count']. So
this stores the database element, Total View Count as an integer in
the TotalView array.
I started to learn how to use Google Charts today and I'm a bit stuck.
I have dynamic data (changes about 3-4 times a day) to pump into the chart (Pie Chart). I'm using AJAX as the data source and PHP as my backend.. I tried to do it this way but to no avail:
AJAX:
<?php
include $_SERVER['DOCUMENT_ROOT'].'/includes/galaxy-connect.php';
$database = new Connection();
$database = $database->Connect();
$statement = $database->Prepare(" SELECT COUNT(Membership_Level_Name) AS MemTotal, Membership_Level_Name
FROM membership AS M
LEFT JOIN membership_levels AS L
ON M.`Membership_Level_Id` = L.`Membership_Level_Id`
LEFT JOIN membership_status AS S
ON M.`MembershipStatusId` = S.MembershipStatusId
WHERE M.`MembershipStatusId` = 1
GROUP BY L.`Membership_Level_Name`
ORDER BY L.`Membership_Level_Id` ");
$statement->execute();
$MembershipTotals = $statement->fetchall(PDO::FETCH_ASSOC);
if (!empty($MembershipTotals)) {
foreach ($MembershipTotals as $MembershipTotal) {
$data[] = array(
"cols" => array("id"=>"Membership_Level_Name", "label"=>"Membership Level", "type"=>"varchar"),
array("id"=>"MemTotal", "label"=>"Total", "pattern"=>"", "type"=>"number"),
"rows" => array($MembershipTotal['Membership_Level_Name'], $MembershipTotal['MemTotal'])
);
}
}
echo json_encode($data);
so thats my ajax, and it produces:
(ok wont let me post an image but heres the results)
[{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Start Up","24"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Member","131"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Member Plus","170"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Premier Member","31"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Bronze","97"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Silver","145"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Gold","188"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Affiliate","3"]},{"cols":{"id":"Membership_Level_Name","label":"Membership Level","type":"varchar"},"0":{"id":"MemTotal","label":"Total","pattern":"","type":"number"},"rows":["Charity\/Education","4"]}]
So the next step is to call that data, I took the code from Google Charts "Connecting to a database" (or something like that) page:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = $.ajax({
url: "/ajax/charts/membershiptotals.php",
dataType:"json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240});
}
</script>
Reload the web page and it produces the error:
Table has no columns
I don't understand why though.. I looked at other solutions and posted on Quora and the Google group for the API but to no avail.. could someone tell me whats wrong with the code??
I found the answer:
AJAX was changed to:
<?php
include $_SERVER['DOCUMENT_ROOT'].'/includes/galaxy-connect.php';
$database = new Connection();
$database = $database->Connect();
$statement = $database->Prepare(" SELECT COUNT(Membership_Level_Name) AS MemTotal, Membership_Level_Name
FROM membership AS M
LEFT JOIN membership_levels AS L
ON M.`Membership_Level_Id` = L.`Membership_Level_Id`
LEFT JOIN membership_status AS S
ON M.`MembershipStatusId` = S.MembershipStatusId
WHERE M.`MembershipStatusId` = 1
GROUP BY L.`Membership_Level_Name`
ORDER BY L.`Membership_Level_Id` ");
$statement->execute();
$MembershipTotals = $statement->fetchall(PDO::FETCH_OBJ);
$col1=array();
$col1["id"]="";
$col1["label"]="Membership Type";
$col1["pattern"]="";
$col1["type"]="string";
$col2=array();
$col2["id"]="";
$col2["label"]="Total";
$col2["pattern"]="";
$col2["type"]="number";
$cols = array($col1,$col2);
$rows=array();
foreach ($MembershipTotals AS $MembershipTotal) { //foreach ($Event->TrainingTotals['ConfirmedTotal'] AS $Key => $Value) {
$cell0["v"]=$MembershipTotal->Membership_Level_Name;
$cell1["v"]=intval($MembershipTotal->MemTotal);
$row0["c"]=array($cell0,$cell1);
array_push($rows, $row0);
}
$data=array("cols"=>$cols,"rows"=>$rows);
echo json_encode($data);
which made it a bit easier and then on the actual page:
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
function drawChart() {
var jsonData = $.ajax({
url: "/ajax/charts/membershiptotals.php",
dataType:"json",
async: false
}).responseText;
// Create our data table out of JSON data loaded from server.
var data = new google.visualization.DataTable(jsonData);
var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, {title:'Membership Bookings', width: 800, height: 500});
}
</script>
Basically I had to clearly declare the columns, and the intval is to turn it into a integer, otherwise it returns the number as a string which Google doesn't like.. hope this helps anyone :)
thanks to Harish for an answer but I needed it more dynamic :-)
this is the format of the array to be passed.
javascript:
var jsondata; //json data recived from php script
var data = google.visualization.arrayToDataTable(jsondata);
php:
$data = array(
array('Membership Level', 'MemTotal'),
array('Member Plus', 170),
array('Member', 131)
);
echo json_encode($data);
Your have to pass Json array not object.
I'm strugling getting data from PHP into a graph. I have the following pieces of code on 1 php page. First the simple part:
$sql = "SELECT * FROM (SELECT timestamp, CurrentKelvin, TargetKelvin, WeatherTempKelvin FROM `rawdata` ORDER BY `rawdata`.`timestamp` DESC LIMIT 10) AS ttbl ORDER BY `timestamp` ASC;";
$results = mysqli_query($con,$sql);
$ChartData = array();
foreach($results as $result)
{
$ChartData[] = array( (int)$result['CurrentKelvin'],(int)$result['TargetKelvin']);
}
$ChartData = json_encode($ChartData);
Then the javascript part:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('number', 'CurrentKelvin');
data.addColumn('number', 'TargetKelvin');
alert( <?php echo json_encode($ChartData); ?>);
data.addRows( <?php echo json_encode($ChartData); ?> );
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data);
}
</script>
<!--Div that will hold the pie chart-->
<div id="chart_div"></div>
When i run the above the alert command shows the following output:
[[292,290],[292,290],[291,290],[291,290],[291,290],[291,290],[291,290],[291,290],[291,290],[291,290]]
But the data.addRows line generates the following error:
Error: Argument given to addRows must be either a number or an array
Changing the data.addRows to something simple (and changing data.addColumn to string, with the same array construction, I do get a graph:
data.addRows([
['Ivan', 5],
['Igor', 7],
['Felix', 8],
['Bob', 4]
]);
I just can't figure out what is going wrong. Any help is appreciated.
Answer given by Dinesh worked:
var json_arr = <?php echo json_encode($ChartData); ?>;
data.addRows(JSON.parse(json_arr));
I can grab the number of users who signed up a specific date by using:
$query = "SELECT COUNT(*), DATE(FROM_UNIXTIME(time)) as date
FROM user GROUP BY DATE(FROM_UNIXTIME(time))";
Google Charts supplies the following JS function for drawing the graph
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Day');
data.addColumn('number', 'Users');
data.addRows([
['03-22-2012', 1000],
['03-23-2011', 1170]
]);
var options = {
title: 'Signups'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
How do I use my database query with data.addRows via ajax? Im stuck here..help is appreciated!
Thanks
Here solved by using a test table stackoverflow with one row, test_ (a timestamp) to mimick what you describe above :
time_
-------------------
2013-07-07 13:23:31
2013-07-07 13:23:44
2013-07-09 13:23:50
2013-07-08 13:23:57
2013-07-09 13:24:07
2013-07-09 13:24:14
googlechart.php, which output will be fetched through AJAX :
<?
mysql_connect('localhost','root','xxx');
mysql_select_db('test');
$SQL='SELECT COUNT(*) as c, DATE(time_) as date FROM stackoverflow GROUP BY DATE(time_)';
$result=mysql_query($SQL);
$a = array();
$a['cols'][] = array('type' => 'string', 'label' => 'Day');
$a['cols'][] = array('type' => 'number', 'label' => 'Users');
while($row = mysql_fetch_assoc($result)) {
$a['rows'][]['c']=array(
array('v' => $row['date']),
array('v' => $row['c'])
);
}
echo json_encode($a);
?>
googlechart.html (actual page) using jQuery AJAX and produces a google chart as described above :
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">google.load('visualization', '1.0', {'packages':['corechart']});</script>
<script type="text/javascript">
function drawChart(json) {
var data = new google.visualization.DataTable(json);
var options = {
title: 'Signups'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
$(document).ready(function() {
$.ajax({
url: 'googlechart.php',
success : function(json) {
drawChart(json);
}
});
});
</script>
<div id="chart_div" style="width:500px;height:400px;"></div>
result :