I have an Array $data composed as following :
$data[$k]['id'] = $row['iddevice'];
$data[$k]['temp_00'] = $row['temp_00'];
$data[$k]['temp_01'] = $row['temp_01'];
$data[$k]['temp_02'] = $row['temp_02'];
$data[$k]['temp_03'] = $row['temp_03'];
$data[$k]['temp_04'] = $row['temp_04'];
I have only two elements in this Array, so echo count($data); return 2
I am using Morris.js to create a line chart, below an example of working code :
$(function() {
Morris.Line({
element: 'morris-area-chart',
data: [
{ y: '00h', 1:57, 2:41},
{ y: '01h', 1:62, 2:98},
{ y: '02h', 1:44, 2:43},
{ y: '03h', 1:67, 2:84},
],
xkey: 'y',
parseTime:false,
ykeys: [1,2,3],
pointSize: 2,
hideHover: 'auto',
labels: ['Capteur X', 'Capteur Y']
});

My problem is as soon as I try to use PHP to use the values from my $data it doesn't work, the chart doesn't load any values.
Morris.Line({
element: 'morris-area-chart',
data: [
{ y: '00h', <?php $i = 0; while ($i <= count($data)-1) { echo $data[$i]['id'].":".round($data[$i]['temp_00'],2); $i++; }?>},
{ y: '01h', <?php $i = 0; while ($i <= count($data)-1) { echo $data[$i]['id'].":".round($data[$i]['temp_01'],2); $i++; }?>},
{ y: '02h', <?php $i = 0; while ($i <= count($data)-1) { echo $data[$i]['id'].":".round($data[$i]['temp_02'],2); $i++; }?>},
{ y: '03h', <?php $i = 0; while ($i <= count($data)-1) { echo $data[$i]['id'].":".round($data[$i]['temp_03'],2); $i++; }?>},
],
For me, the algorithm is fine :
$i is lower or equal to count($data)-1 (so 2-1 = 1 so we should stay in the loop two times)$i by oneWhat am I thinking or doing wrong here ?
Also when I initialize $i to one rather than zero, I can get the values for the second entry in my $data Array

(I prefer to say that I am not a developer so this code might not be the cleanest I agree)
EDIT :
Pastebin to the var_dump of $data : http://pastebin.com/dYNtLxqX
Screenshot when using Forbs' solution (Chart doesn't load at all) :

The SQL query I am using to populate $data Array :
select iddevice, data.ip, type, description,
avg(case when hour(date) = 00 then temp end) as temp_00,
avg(case when hour(date) = 01 then temp end) as temp_01,
avg(case when hour(date) = 02 then temp end) as temp_02,
...
avg(case when hour(date) = 22 then temp end) as temp_22,
avg(case when hour(date) = 23 then temp end) as temp_23
from data, device
where date >= '2017-03-20' and
date < '2017-03-21' and
device.ip = data.ip
group by ip
order by iddevice;
The Array is populate with this query using a while loop
$results = $conn->query($sql);
$k = 0;
$data = array();
while ($row = $results->fetch_assoc()) {
$data[$k]['temp_00'] = $row['temp_00'];
$data[$k]['temp_01'] = $row['temp_01'];
$data[$k]['temp_02'] = $row['temp_02'];
$data[$k]['temp_03'] = $row['temp_03'];
...
$k++;
}
This is my suggestion for a different way to do this. It cuts down on the repeated code, and minimizes the PHP/JS mixing.
First, build your array a little differently as you fetch the rows from your query:
while ($row = $results->fetch_assoc()) {
// Loop over each of the temp_x columns
for ($i=0; $i < 4; $i++) {
$x = str_pad($i, 2, '0', STR_PAD_LEFT);
// add the value for each temp_x to a temporary array, using time for a key
$temp = is_null($row["temp_$x"]) ? 'null' : round($row["temp_$x"], 2);
$times[$x][] = $row['iddevice'] . ':' . $temp;
}
}
Next, format the values of each array in the temporary array
foreach ($times as $time => $temps) {
$data[] = "{ y: '{$time}h', " . implode(', ', $temps) . '}';
}
Then convert the $data array to a string:
$data = implode(",\n", $data);
That way, all the PHP you'll need in the JS part is:
Morris.Line({
element: 'morris-area-chart',
data: [ <?php echo $data ?> ]
There may be a better way using json_encode. If you change the code inside the while loop that fetches rows from your database just slightly:
for ($i=0; $i < 4; $i++) {
$x = str_pad($i, 2, '0', STR_PAD_LEFT);
$temp = is_null($row["temp_$x"]) ? null : round($row["temp_$x"], 2);
$times[$x]['y'] = $x.'h';
$times[$x][$row['iddevice']] = $temp;
}
Then $data can be formed using json_encode. (The array_values is used to reindex the array with numeric indexes so it will render as an array in the JSON output instead of an object.)
$data = json_encode(array_values($times));
And in the JS:
Morris.Line({
element: 'morris-area-chart',
data: <?php echo $data ?>
// note: no [] brackets around $data in this version
Whether or not this will work depends on whether or not it's okay for all the keys to be strings, because JSON keys are strings, so you'll get output like
{ "y": "01", "1": 17.62, "2": 19.52 }
instead of
{ y: '01', 1: 17.62, 2: 19.52 }
I think it should probably work anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With