在PHP中循环获取Array值

时间:2017-03-22 19:09:02

标签: javascript php arrays morris.js

我有一个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']
});

Morris.js Line Chart

我的问题是,当我尝试使用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等于0
  • 虽然$i低于或等于count($data)-1(所以2-1 = 1所以我们应该留在循环中两次)
  • 显示此元素的ID和温度值
  • $i增加一个

我在这里想什么或做错了什么?

当我将$i初始化为1而不是0时,我可以获取$data数组中第二个条目的值

Morris.js Chart 2

(我更喜欢说我不是开发人员所以这段代码可能不是我同意的最干净的代码)

编辑:

  • Pastebin到var_dump的{​​{1}}:http://pastebin.com/dYNtLxqX

  • 使用Forbs时的屏幕截图&#39;解决方案(图表根本没有加载): Morris.js Chart 3

  • 我用来填充$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;
    

3 个答案:

答案 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()函数所需的字符串。希望这是有道理的。

相关问题