Adry Adry - 1 month ago 5
PHP Question

Display php nested array results continuously in two column table

I have a nested array grouping three other arrays: $online, $busy and $offline, in order to display results in this exactly order.

$conteudo = array($online, $ocupado, $offline);


The desired result would be a table in two columns to display results in continuous flow like this:

online1 | online2
online3 | busy1
busy2 | offline1
offline2| offline3
offline4|


I've been trying lots of
foreach
loops and playing around changing the html tags, but the closest I can arrive of the desired result is this:

<table width='100%' cellpadding='5' border="1">
<?php
$i = 1; //contador de colunas
$max_colunas = 2; // numero de colunas
foreach ($conteudo as $row) {
echo "<tr>";
foreach ($row as $col) {
foreach ($col as $cell) {
if ($i == 1) {
echo "<td>" . $cell . "</td>";
} elseif ($i == $max_colunas){
echo "<td>" . $cell . "</td></tr>";
$i = 0;
} else {
echo "<td>" . $cell . "</td>";
}
$i++;
}
}
echo "</tr>";
}


This code will output a table like this:

onine1 | online2 |online3
busy1 | busy2 |
offline1|offline2 |offline3|offline4


I can't find out why it ignores completely
$max_colunas
, seems like it prints all the elements inside the array in row.

If I remove lines:

echo "<tr>";
echo "</tr>";


from beginning and end of
foreach
it will output all in a row like this:

onine1 | online2 |online3 | busy1 | busy2 |offline1|offline2 |offline3|offline4


Any suggestions to get the desired output format will be so appreciated.




Edited on 17/01:

This is how I'm getting the arrays from:

//group people
$online = array(); //group online
$ocupado = array(); //group ocupado
$offline = array(); //group offline

//select people to group
$atendentes = mysql_query("SELECT nome FROM atendentes ORDER BY nome") or die(mysql_error());
$atendentedb = array();

//put selected people in array
while ($row = mysql_fetch_assoc($atendentes)) {
$atendentedb[] = array('nome' => $row["nome"], 'online' => false);
}


//take people online now and check in selected people
$names = modWhosonlineCustom::getOnlineUserNames();

foreach ($names as $name):
//foreach ($atendentedb as $atendente):
for($i = 0; $i < count($atendentedb); $i++):
$att = strtolower($name->username);

if ($atendentedb[$i]['nome'] == $att):
$atendentedb[$i]['online'] = true;
break;
endif;

endfor;
endforeach;

//check each selected people
foreach ($atendentedb as $atendente) :
//save temporary data
$online_ = $atendente['online'];
$nome_ = $atendente['nome'];

//if selected people online
if ($online_) :
//take status to show
$status = mysql_query("SELECT status FROM atendentes WHERE nome = '$nome_' LIMIT 1") or die(mysql_error());
while ($row = mysql_fetch_assoc($status)):
$statusdb = $row["status"];
endwhile;

//verify and save deppending on status
switch ($statusdb):

//if online
case "disponivel":
$descricao = mysql_query("SELECT hp_online FROM atendentes WHERE nome = '$nome_' LIMIT 1") or die(mysql_error());
while ($row = mysql_fetch_assoc($descricao)):
$online[] = array('info'=>$row['hp_online']);
endwhile;
break;

//if busy
case "ocupado":
$descricao = mysql_query("SELECT hp_busy FROM atendentes WHERE nome = '$nome_' LIMIT 1") or die(mysql_error());
while ($row = mysql_fetch_assoc($descricao)):
$ocupado[] = array('info'=>$row['hp_busy']);
endwhile;
break;
endswitch;

//if offline
else:
$descricao = mysql_query("SELECT hp_offline, horario FROM atendentes WHERE nome = '$nome_' LIMIT 1") or die(mysql_error());
while ($row = mysql_fetch_assoc($descricao)):
$offline[] = array('info'=>$row['hp_offline'], 'horario'=>$row['horario']);
endwhile;

endif;
endforeach;


EDITED

So after following help instructions from DaveRandom I got to this code, which is really a drop away from the right format, except for the "mysterious" behaviour with results coming from array
$offline
, that are displaying all in "block" (all cells in a row, or all cells in a column) while the other arrays are displaying perfectly(??).

//group people
$online = $ocupado = $offline = array();

//select people to group
$query = "SELECT nome, status, hp_online, hp_busy, hp_offline, horario
FROM atendentes
ORDER BY nome";
$atendentes = mysql_query($query) or die(mysql_error());
$atendentedb = array();

// put selected people in array
while ($row = mysql_fetch_assoc($atendentes)) {
$atendentedb[strtolower($row['nome'])] = array_merge($row, array('online' => FALSE));
}

//take people online now and check in selected people
$names = modWhosonlineCustom::getOnlineUserNames();
foreach ($names as $name) {
$uname = strtolower($name->username);
if (isset($atendentedb[$uname])) $atendentedb[$uname]['online'] = TRUE;
}

//check each selected people
foreach ($atendentedb as $name => $atendente) {

//if selected people online
if ($atendente['online']) {

//verify and save deppending on status
switch ($atendente['status']) {

//if online
case 'disponivel':
$atendentedb[$name]['info'] = $online[] = $atendente['hp_online'];
break;

//if busy
case 'ocupado':
$atendentedb[$name]['info'] = $ocupado[] = $atendente['hp_busy'];
break;

}

//if offline
} else {

$atendentedb[$name]['info'] = $offline[] = $atendente['hp_offline'];
$atendentedb[$name]['info'] = $offline[] = $atendente['horario'];

}

}

//*******Display Results
$conteudo = array_merge($online, $ocupado, $offline);
$max_colunas = 2; // numero de colunas

// Start the table
echo '<table width="100%" cellpadding="5" border="1">'."\n";

// Loop all the objects
for ($i = 0, $j = 0; isset($conteudo[$i]); $i++) {
if ($j == 0) {
// Output the beginning of a row
echo " <tr>\n";
}
// Always output a data cell
echo " <td>$conteudo[$i]</td>\n";
if (++$j >= $max_colunas) {
// Output the end of a row and reset the cell counter
echo " </tr>\n";
$j = 0;
}
}

if ($j) {
// We may end up with an incomplete row at the end, so pad it with empty cells
// and close the row
while ($j++ < $max_colunas) {
echo " <td></td>\n";
}
echo " </tr>\n";
}

// Close the table
echo "</table>";

Answer

I would say that the first thing to do here is to "flatten" the array - having the multiple dimensions makes this a lot more complicated than it needs to be. So rather than creating $conteudo like this:

$conteudo = array($online, $ocupado, $offline);

...do this instead:

$conteudo = array_merge($online, $ocupado, $offline);

Then you can do this:

$max_colunas = 2; // numero de colunas

// Start the table
echo '<table width="100%" cellpadding="5" border="1">'."\n";

// Loop all the objects
for ($i = 0, $j = 0; isset($conteudo[$i]); $i++) {
  if ($j == 0) {
    // Output the beginning of a row
    echo "  <tr>\n";
  }
  // Always output a data cell
  echo "    <td>$conteudo[$i]</td>\n";
  if (++$j >= $max_colunas) {
    // Output the end of a row and reset the cell counter
    echo "  </tr>\n";
    $j = 0;
  }
}

if ($j) {
  // We may end up with an incomplete row at the end, so pad it with empty cells
  // and close the row
  while ($j++ < $max_colunas) {
    echo "    <td></td>\n";
  }
  echo "  </tr>\n";
}

// Close the table
echo "</table>";

See it working

EDIT

Try this code for generating your arrays. Note that the structure of your output arrays has been altered to fit my code sample above - if you use this data anywhere else in you script, you will need to modify that code as well. I have modified this so that there is only one database query, which would seem to be all that is required. I have also modified it so that the $atendentedb holds all the user data, including the status and info keys, and all rows contain a horario key.

Because of the fact that your input arrays originally contained more data than the ones created by this code will, the code may need further modification - but try this out and see how you get on.

//group people
$online = $ocupado = $offline = array();

//select people to group
$query = "SELECT nome, status, hp_online, hp_busy, hp_offline, horario
          FROM atendentes
          ORDER BY nome";
$atendentes = mysql_query($query) or die(mysql_error());
$atendentedb = array();

// put selected people in array
while ($row = mysql_fetch_assoc($atendentes)) {
  $atendentedb[strtolower($row['nome'])] = array_merge($row, array('online' => FALSE));
}

//take people online now and check in selected people
$names = modWhosonlineCustom::getOnlineUserNames();
foreach ($names as $name) {
  $uname = strtolower($name->username);
  if (isset($atendentedb[$uname])) $atendentedb[$uname]['online'] = TRUE;
}

//check each selected people
foreach ($atendentedb as $name => $atendente) {

  //if selected people online
  if ($atendente['online']) {

    //verify and save deppending on status
    switch ($atendente['status']) {

      //if online
      case 'disponivel':
        $atendentedb[$name]['info'] = $online[] = $atendente['hp_online'];
        break;

      //if busy
      case 'ocupado':
        $atendentedb[$name]['info'] = $ocupado[] = $atendente['hp_busy'];
        break;

    }

  //if offline
  } else {

    $atendentedb[$name]['info'] = $offline[] = $atendente['hp_offline'].' '.$atendente['horario'];

  }

}
Comments