我有一个Array $数据组成如下:
$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'];
此数组中只有两个元素,因此echo count($data);
返回2
我使用Morris.js创建折线图,下面是工作代码的示例:
$(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']
});
我的问题是,当我尝试使用PHP来使用我$data
中的值时,它不起作用,图表不会加载任何值。
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++; }?>},
],
对我来说,算法很好:
$i
低于或等于count($data)-1
(所以2-1 = 1所以我们应该留在循环中两次)$i
增加一个我在这里想什么或做错了什么?
当我将$i
初始化为1而不是0时,我可以获取$data
数组中第二个条目的值
(我更喜欢说我不是开发人员所以这段代码可能不是我同意的最干净的代码)
编辑:
Pastebin到var_dump
的{{1}}:http://pastebin.com/dYNtLxqX
我用来填充$data
数组的SQL查询:
$data
使用while循环
填充此查询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;
答案 0 :(得分:2)
这是我对不同方法的建议。它减少了重复的代码,并最大限度地减少了PHP / JS的混合。
首先,在从查询中获取行时,以不同的方式构建数组:
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;
}
}
接下来,格式化临时数组中每个数组的值
foreach ($times as $time => $temps) {
$data[] = "{ y: '{$time}h', " . implode(', ', $temps) . '}';
}
然后将$data
数组转换为字符串:
$data = implode(",\n", $data);
这样,JS部分中你需要的所有PHP都是:
Morris.Line({
element: 'morris-area-chart',
data: [ <?php echo $data ?> ]
使用json_encode
可能有更好的方法。如果您更改while
循环内的代码,只需稍微从数据库中获取行:
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;
}
然后可以使用$data
形成json_encode
。 (array_values
用于使用数字索引重新索引数组,因此它将在JSON输出中呈现为数组而不是对象。)
$data = json_encode(array_values($times));
在JS中:
Morris.Line({
element: 'morris-area-chart',
data: <?php echo $data ?>
// note: no [] brackets around $data in this version
这是否有效取决于所有键是否为字符串都是可以的,因为JSON键是字符串,所以你得到像
这样的输出{ "y": "01", "1": 17.62, "2": 19.52 }
而不是
{ y: '01', 1: 17.62, 2: 19.52 }
我认为无论如何它应该可行。
答案 1 :(得分:0)
你的问题在循环中
while ($i <= count($data)-1)
这应该是
while ($i <= (count($data)-1))
或者
while ($i < count($data))
效果更好
答案 2 :(得分:0)
您可以进一步优化它。
Morris.Line({
element: 'morris-area-chart',
data: [
<?php
foreach($data as $sensor) {
foreach($sensor as $key => $value) {
if($key == 'id') {
$id = $value;
} else {
$tempTime[$key][$id] = $value;
}
}
}
$i = 0;
foreach($tempTime as $time) {
echo sprintf("{ y: '%02dh', ",$i);
foreach($time as $key => $value) {
echo sprintf("%d:%d, ",$key, round($value,2);
}
echo "},";
$i++;
}
?>
],
xkey: 'y',
parseTime:false,
ykeys: [1,2,3],
pointSize: 2,
hideHover: 'auto',
labels: ['Capteur X', 'Capteur Y']
});
通过这种方式,如果你的阵列变大,你将不必重复自己。
解释
foreach
是一个迭代数组的函数。
第一个foreach循环只是对数组进行重新排序,以便在最后的foreach
循环中使用它(当你从sql创建数组时,你可以做到这一点,但我不能看看你是如何从你的帖子那样做的)
最后一个foreach
循环只打印出Morris.line()
函数所需的字符串。希望这是有道理的。