Get array values ​​in a loop in PHP

I have Array $ data composed like this:

$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 only have two elements in this array, so echo count($data);

return2

I am using Morris.js to create a line chart, below is a working code example:

$(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 string diagram

My problem is as soon as I try to use PHP to use values ​​from mine $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 equals 0
  • while is $i

    less than or equal count($data)-1

    (so 2-1 = 1, so we have to stay in the loop twice)
  • Display IDs and temperatures for these elements.
  • Increment by $i

    one

What am I thinking or doing wrong here?

Also when I initialize $i

to one and not zero, I can get the values ​​for the second entry in my $data

Array

Morris.js Chart 2

(I prefer to say that I am not a developer, so this code may not be the cleanest I agree)

EDIT:

  • Pastebin for var_dump

    of $data

    : http://pastebin.com/dYNtLxqX

  • Screenshot when using Forbs solution (diagram not loading at all): Morris.js Chart 3

  • The SQL query I'm using to populate the $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 filled with this request 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++;
    }
    
          

+3


source to share


3 answers


This is my suggestion for another way to do this. It cuts down on repetitive code and minimizes PHP / JS mixing.

First, create your array a little differently when you fetch the strings 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 a temporary array

foreach ($times as $time => $temps) {
    $data[] = "{ y: '{$time}h', " . implode(', ', $temps) . '}';
}

      

Then convert the array $data

to string:

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

      

So all the PHP you need in the JS part is as follows:

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

      


There might be a better way to use json_encode

. If you change the code inside the loop while

that slightly fetches rows from your database:



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 it $data

can be formed using json_encode

. ( array_values

used to override an array with numeric indices so that it appears as an array in the JSON output instead of an object.)

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

      

And in 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 it is okay for all keys to be strings, because JSON keys are strings, so you get an output like

{ "y": "01", "1": 17.62, "2": 19.52 }

      

instead

{ y: '01', 1: 17.62, 2: 19.52 }

      

I think this should probably work anyway.

+2


source


Your problem is in the loop

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

      

It should be

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

      



or

while ($i < count($data))

      

works better

0


source


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

      

This way, if your array gets large, you don't have to iterate over yourself.

Explanation foreach

is a function that iterates through an array. The first foreach loop just reorders the array in such a way that it is easy to use in the last loop foreach

(you would do that when you first create the array from sql, but I could not figure out how you did it from my post) The last loop foreach

just prints out the lines needed for the function Morris.line()

. Hope this makes sense.

0


source







All Articles