Print Array Top to Bottom in table instead of Left to Right using PHP

Viewed 1739

I am trying to write a logic to display records top to bottom instead of left to right in the table.

Here is my attempt:

<?php $options = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"); ?>
<table border="1" colspan="0" cellspan="0">
    <?php
    $htmldata = "";
    $counter = 1;

    $rowcount = ceil(count($options) / 3);

    for ($i = 0; $i < count($options); $i++) {
        echo $counter % 3 ."<br/>";

        if ($counter % 3 == 1) {
            $htmldata .= "<tr>";
            $htmldata .= "<td>".$options[$i]."</td>";
        }
        if ($counter % 3 == 2) {
            $htmldata .= "<td>".$options[$i]."</td>";
        }
        if ($counter % 3 == 0) {
            $htmldata .= "<td>".$options[$i]."</td>";
            $htmldata .= "</tr>";
        }
        $counter++;
    }
    echo $htmldata;
    exit;
    ?>
</table>

Below is current code output in the table.

Actual output

But I need the table to output like this.

Expected output

How can I achieve this?
Can you guys please help me to write this logic?
Also, it currently is showing 10 records, but it may be much more or less, so we need the code to be dynamic.

Any help will be appreciated. Thanks in advance!

NOTE: It must have only 3 columns for any numbers of records and output must be same as displayed in the second picture example for 10 records.

4 Answers

Hopefully my final answer (after all the editing)

<?php
// feel free to change the values in these variables
$options = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
$numCols = 3; // the number of columns to present
$pad = false; // whether to add blank <td> in final row

// don't alter these variables
$rows = (int)ceil(count($options) / $numCols); // number of rows of the column with most rows
$c = count($options) % $numCols; // how many columns have records on the final row
$col = 1; // current column

// iterate over the columns
for ($j = 0; $j < $numCols; $j++) {
    // iterate over rows
    for ($i = 0; $i < $rows; $i++) {
        // if iteration is last line and on a column with extra data
        // or if the iteration is not the last row
        // or if the last row perfectly fits the column count
        if (($col <= $c && $i == $rows - 1) || $i != $rows - 1 || $c == 0) {
            // remove the first element from the options array
            $arr[$i][$j] = array_shift($options);
        }
    }
    // move onto the next column
    $col++;
}

// create the extra <td> elements in the final row
if ($pad) {
    $arr[count($arr) - 1] = array_pad($arr[count($arr) - 1], $numCols, null);
}
?>
<table border="1" colspan="0" cellspan="0">
    <?php for ($i = 0; $i < count($arr); $i++) { ?>
    <tr>
        <?php for ($j = 0; $j < count($arr[$i]); $j++) { ?>
        <td><?= $arr[$i][$j]; ?></td>
        <?php } ?>
    </tr>
    <?php } ?>
</table>

I have edited the answer I originally posted as it was broken and long-winded. This solution is neater and works better than the previous.

At the time of writing this answer I hadn't seen the edit about a fixed number of columns so there is a variable that can change the column count if necessary. Feel free to change the column count ($numCols) and also the number of elements in the array. This is here should you ever need to change the requirements of your application.

There are a few thing you can fiddle with if you like. They are as follows:

  • $options
    This is simply your array of data. This can be whatever the heck you want. The table will be created according to this data from top to bottom as requested.
  • $numCols
    Perhaps you want to rename this, it really doesn't matter. It is short for 'number of columns' and is exactly that; whatever integer you put here, you will get that many <td> elements in that row, or, if you prefer to not read them in the HTML way, then you will have that many columns with the subsequent row count depending on the provided data.
  • $pad
    This is because I noticed that the last row had fewer records - unless $options length was divisible, with no remainder, by $numCols.
    To fix this I added this choice. It is used after the for loop has created the array, and will just pad out the final row with null values so that you don't have the blank space to the right of the final row.
    Naturally, it is entirely up to you whether you want that. Personally, I'd opt to set $pad to true since I think that it makes the table look neater.

The rest of the code I encourage you to not alter as it will work correctly.
Obviously, if you use this code a lot then you can wrap it in a function; although if you do this, I strongly discourage that you do as you originally did and start creating a string to store your table in.
It is bad practice and can cause mistakes. For instance, you might forget to close the table - something you did by using the exit keyword - which would go unnoticed by many modern browsers as they would still show the desired outcome, but your code would then fail a validator. Therefore, if you wish to use a function ensure that it is only the PHP code. Then just call it on an array and iterate as I have done at the end (by which I mean, the table part with the for loop is not part of the function).

I honestly can't believe how long I spent doing this!

Output of code

Try this:

<?php
$options = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16");
$elems = count($options);
// set the # of rows you want to show
$rows=5;
// calculate # of columns
$cols=ceil($elems/$rows);


echo "<table style='border: 2px solid black;'>";
for($r=0; $r<$rows; $r++)
{
    echo '<tr>';
    $shift=0;
    for($c=0; $c<$cols; $c++)
    {
        echo "<td style='border: 1px solid blue;'>";
        if($r+$shift < $elems)
        {
        echo $options[$r+$shift];
        }
        echo '</td>';

        $shift+=$rows;
    }
    echo '</tr>';
}
echo '</table>';
?>

Try this:

<?php
function getTableHtml(array $data, int $colLength): string
{
    $result = '';

    $rowNumber = 0;
    $rows = [];
    foreach (array_values($data) as $k => $v) {
        if ($k % $colLength === 0) {
           ++$rowNumber;
           $rows[$rowNumber] = '';
        }

        $rows[$rowNumber] .= '<td>';
        $rows[$rowNumber] .= htmlentities($v);
        $rows[$rowNumber] .= '</td>';
        $rows[$rowNumber] .= PHP_EOL; // optional formatting
    }

    $result = '<table><tr>' . join('</tr><tr>', $rows) . '</tr></table>';

    return $result;
}

Try live: https://3v4l.org/A7erq

You can do something links this. first loop and store element in proper way. then simply it in table. NOTE :

You have to fix row or column (Here I am assuming you have fix 3 rows). Your desired output has issue as first row has 4 rows and others have 3

<?php 
$options = range(1,10);
$new_array = array();
$rows = 3;
foreach ($options as $value) {
  $new_array[$value % $rows][] = $value;    
}

?>
<table border="1" colspan="0" cellspan="0">
    <?php
        $htmldata = "";
        foreach ($new_array as $key => $value) {
          echo "<tr>";
          foreach ($value as $option) {
            echo "<td>".$option."</td>";
          }
          echo "</tr>";
        }  
    ?>
</table>

Output will be

enter image description here

Related