Reputation: 1
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
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