简体   繁体   English

在PHP中循环获取Array值

[英]Get Array values in a loop in PHP

I have an Array $data composed as following : 我有一个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'];

I have only two elements in this Array, so echo count($data); 我在这个数组中只有两个元素,所以echo count($data); return 2 返回2

I am using Morris.js to create a line chart, below an example of working code : 我正在使用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折线图

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. 我的问题是,当我尝试使用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++; }?>},

  ],

For me, the algorithm is fine : 对我来说,算法很好:

  • $i equal 0 $ i等于0
  • while $i is lower or equal to count($data)-1 (so 2-1 = 1 so we should stay in the loop two times) $i低于或等于count($data)-1 (所以2-1 = 1所以我们应该保持循环两次)
  • Display the ID and temperature values for this elements 显示此元素的ID和温度值
  • Increment $i by one 增加$i一个

What 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初始化$i 1而不是0时,我可以获取$data数组中第二个条目的值

Morris.js图2

(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 粘贴到$datavar_dumphttp//pastebin.com/dYNtLxqX

  • Screenshot when using Forbs' solution (Chart doesn't load at all) : 使用Forbs解决方案时的屏幕截图(图表根本不加载): Morris.js图3

  • The SQL query I am using to populate $data Array : 我用来填充$data数组的SQL查询:

     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 使用while循环使用此查询填充Array

     $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. 它减少了重复的代码,并最大限度地减少了PHP / JS的混合。

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数组转换为字符串:

$data = implode(",\n", $data);

That way, all the PHP you'll need in the JS part is: 这样,JS部分中您需要的所有PHP都是:

Morris.Line({
  element: 'morris-area-chart',
  data: [ <?php echo $data ?> ]

There may be a better way using json_encode . 使用json_encode可能有更好的方法。 If you change the code inside the while loop that fetches rows from your database just slightly: 如果更改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;
}

Then $data can be formed using json_encode . 然后可以使用json_encode形成$data (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.) array_values用于使用数字索引重新索引数组,因此它将呈现为JSON输出中的数组而不是对象。)

$data = json_encode(array_values($times));

And in the JS: 而在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 这是否有效取决于所有键是否可以成为字符串,因为JSON键是字符串,所以你会得到像

{ "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. 我认为无论如何它应该可行。

Your problem is in the loop 你的问题在循环中

while ($i <= count($data)-1)

This should be 这应该是

while ($i <= (count($data)-1))

Or 要么

while ($i < count($data))

works better 效果更好

You can optimize it even more. 您可以进一步优化它。

  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']
});

In that way, if your array gets big you won't have to repeat yourself. 这样,如果你的阵列变大,你将不必重复自己。

Explanation foreach is a function that iterates through an array. 解释foreach是一个迭代数组的函数。 The first foreach loop just reorders the array so that it is easy'er to use in the last foreach loop (you would proporly do this when you create the array from the sql in the first place, but I couldn't see how you did that from your post) The last foreach loop just print out the strings needed for the Morris.line() function. 第一个foreach循环只是对数组进行重新排序,以便在最后一个foreach循环中使用它很容易(当你从sql创建数组时,你会先做这个,但我看不出你是怎么做的来自你的帖子)最后一个foreach循环只打印出Morris.line()函数所需的字符串。 Hope this make sense. 希望这是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM