user4699714
user4699714

Reputation: 1

PHP Tree Structure to Html Table

I have a scenario where I have a tree structure data like this:

    $tree = array(
    1 => array(
        4 => array(),
        5 => array()
    ),
    2 => array(
        6 => array(),
        7 => array(
            11 => array()
        ),
        8 => array(
            12 => array(
                14 => array(),
                15 => array()
            )
        ),
    ),
    3 => array(
        9 => array(),
        10 => array(
            13 => array()
        )
    )
);

How to create a html table using PHP recursive function like this:

1           |       2           |       3       |
4       5   |   6   7   |   8   |   9       10  |
            |       |11 |   12  |       |   13  |
                        |14 |15 |

I am using following PHP code:

function tree(array $data, &$tree = array(), $level = 0) {
    // init
    if (!isset($tree[$level])) $tree[$level] = array(count($array));

    foreach ($data as $key => $value) {

        // if value is an array, push the key and recurse through the array
        if (is_array($value)) {
            $tree[$level][] = $key;
            tree($value, $tree, $level+1);
        }
        // otherwise, push the value
        else {
           $tree[$level][] = $value;
        }
    }
}

function make_table($array)
{
    $output = '';
    foreach($array as $item => $tr)
    {
        $c = 100/count($tr);
        $output .= "<tr>";

        foreach($tr as $th => $val)
        {           
            $output .= "<th style='width:" . $c . "%'>" . $val . "</th>";
        }

        $output .= "</tr>";     
    }

    return $output;
}

But the above code does not handle empty space like in third row of first column.

1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 |
14 | 15 |

Upvotes: 0

Views: 1295

Answers (1)

chocochaos
chocochaos

Reputation: 1596

You need some way to keep track of colspans and the position of every cell in the table, and then fill the gaps with empty cells.

I wrote this today, it seems to work fine for your example:

<?php

$tree = [
    'Table Title' => [
        1 => [
            4 => [],
            5 => []
        ],
        2 => [
            6 => [],
            7 => [
                11 => []
            ],
            8 => [
                12 => [
                    14 => [],
                    15 => []
                ]
            ],
        ],
        3 => [
            9  => [],
            10 => [
                13 => []
            ]
        ]
    ]
];

// Loop over the tree. Every leaf in the root of the tree
// gets his own table(s).
foreach ($tree as $name => $leaves) {
    $table = [];
    parseLeaf($name, $leaves, $table);
    $table = cleanupRows($table);

    output($table);
}

/**
 * Convert a leaf in the tree to an array to be used to print the tables.
 * The span of a leaf is either the sum of its children's spans,
 * or 1 if it has no children.
 *
 * @param string $name
 * @param array  $leaves
 * @param array  $table
 * @param int    $level
 * @param int    $position
 *
 * @return int
 */
function parseLeaf($name, $leaves, &$table, $level = 0, $position = 0)
{
    if (!empty($leaves)) {
        $span = 0;

        foreach ($leaves as $leafName => $childLeaves) {
            $span += parseLeaf(
                $leafName,
                $childLeaves,
                $table,
                $level + 1,
                $position + $span
            );
        }
    } else {
        $span = 1;
    }

    $table[$level][$position] = getCell($name, $span);;

    return $span;
}

/**
 * Insert empty cells where needed and sort by keys.
 *
 * @param array $table
 *
 * @return array
 */
function cleanupRows($table)
{
    $width = $table[0][0]['span'];

    foreach ($table as $rowNumber => $row) {
        $spanSoFar = 0;
        foreach ($row as $position => $cell) {
            addExtraCells($table, $spanSoFar, $rowNumber, $position);
            $spanSoFar += $cell['span'];
        }
        addExtraCells($table, $spanSoFar, $rowNumber, $width);
        ksort($table[$rowNumber]);
    }
    ksort($table);

    return $table;
}

/**
 * @param array $table
 * @param int   $spanSoFar
 * @param int   $rowNumber
 * @param int   $position
 */
function addExtraCells(&$table, &$spanSoFar, $rowNumber, $position)
{
    while ($spanSoFar < $position) {
        $table[$rowNumber][$spanSoFar] = getCell();
        $spanSoFar += 1;
    }
}

/**
 * @param string $name
 * @param int    $span
 *
 * @return array
 */
function getCell($name = '', $span = 1)
{
    return ['name' => $name, 'span' => $span];
}

/**
 * Print the table.
 *
 * @param array $table
 */
function output($table)
{
    echo '<table border="1">';
    foreach ($table as $row) {
        echo '<tr>';
        foreach ($row as $cell) {
            echo '<td colspan="' . $cell['span'] . '" align="center">';
            echo $cell['name'];
            echo '</td>';
        }
        echo '</tr>';
    }
    echo '</table>';
}

Upvotes: 1

Related Questions