简体   繁体   中英

PHP: build html table with rowspans from associative array

I have the following array

Array
(
    [Germany] => Array
        (                
             [Channels] => Array
                    (
                       [0] => Google Ads
                       [1] => LinkedIn Ads
                       [2] => E-Mail-Marketing
                    )

              [Tools] => Array
                    (
                       [0] => CRM
                    )    
                   
        )

    [USA] => Array
        (                
               [SalesTools] => Array
                    (
                       [0] => Pipedrive
                       [1] => Salesforce
                    )    
        )    
)

and want to show it in a table like this:

    <table>
        <tr>
            <th>Region</th>
            <th>Costcenter</th>
            <th>Costcenter_item</th>

        </tr>
        <tr>
            <td rowspan='4'>Germany</td>
            <td rowspan='3'>Channels</td>
            <td>Google Ads</td>
        </tr>
        <tr>
            <td>Linkedin</td>
        </tr>
        <tr>
            <td>Email Marketing</td>
        </tr>
        <tr>
            <td rowspan='1' >Tools</td>
            <td>CRM</td>
        </tr>

        <tr>
            <td rowspan='2'>USA</td>
            <td rowspan='2'>Sales Tools</td>
            <td>Pipedrive</td>
        </tr>

        <tr>
            <td>Salesforce</td>
        </tr>
    </table>

But I get absolutely confused about the rowspans. I tried using backtracking on the array to count the "leaves" but I couldnt make it work. How can I get the correct rowspan number while building this html table programmatically with php?

  • Here, we need to get how many leaves are there for a key to calculate the row span for a particular td. So in the below snippet, we return sub results for each recursive call which is an array with 0 th index being the td rows and 1 st index being no. of leaves encountered so far.

Snippet:

<?php

function getAllCells($d){
    $res = [];
    $leaves = 0;
    foreach($d as $key => $value){
        if(is_array($value)){
            $sub_res = getAllCells($value);
            $res = array_merge($res, [["<td rowspan='".$sub_res[1]."'>$key</td>", $sub_res[1]]], $sub_res[0]);
            $leaves += $sub_res[1];
        }else{
            $res = array_merge($res, [["<td>$value</td>", 0]]);
            $leaves++;
        }   
    }
    
    return [$res, $leaves];
}
  • Once done, we can build up the table again recursively using the above precomputed td s'. The main catch here is to understand when to open and close a tr .

  • We only close a tr tag if it is the first leaf child. Every other leaf child will reside in it's own tr tags.

Snippet:

<?php

function buildTable($d, $tds, &$ptr, &$table){
    $first_leaf_consumed = false;
    if($ptr == 0) $table .= "<tr>";
    foreach($d as $key => $value){
        if(is_array($value)){
            $table .= $tds[ $ptr++ ][0];
            $sub_res = buildTable($value, $tds, $ptr, $table);  
        }else{
            if(!$first_leaf_consumed){
                $table .= $tds[$ptr++][0] . "</tr>";
                $first_kid_consumed = true; 
            }else{
                $table .= "<tr>". $tds[$ptr++][0] . "</tr>";
            }
        }   
    }
}

Full Code:

<?php

$d = Array(
    'Germany' => Array
        (      
         'Channels' => Array
                (
                   '0' => 'Google Ads',
                   '1' => 'LinkedIn Ads',
                   '2' => 'E-Mail-Marketing'
                ),
          'Tools' => Array
                (
                   '0' => 'CRM'
                ),
                   
        ),
    'USA' => Array
        (                
           'SalesTools' => Array
                (
                   '0' => 'Pipedrive',
                   '1' => 'Salesforce'
                )    
        ),    
);

$tds = getAllCells($d)[0];

$table = <<<EOD
<table border='3'>
        <tr>
            <th>Region</th>
            <th>Costcenter</th>
            <th>Costcenter_item</th>
        </tr>
EOD;

$ptr = 0;

buildTable($d, $tds, $ptr, $table);
function buildTable($d, $tds, &$ptr, &$table){
    $first_leaf_consumed = false;
    if($ptr == 0) $table .= "<tr>";
    foreach($d as $key => $value){
        if(is_array($value)){
            $table .= $tds[ $ptr++ ][0];
            $sub_res = buildTable($value, $tds, $ptr, $table);  
        }else{
            if(!$first_leaf_consumed){
                $table .= $tds[$ptr++][0] . "</tr>";
                $first_kid_consumed = true; 
            }else{
                $table .= "<tr>". $tds[$ptr++][0] . "</tr>";
            }
        }   
    }
}

$table .= "</table>";
echo $table;

function getAllCells($d){
    $res = [];
    $leaves = 0;
    foreach($d as $key => $value){
        if(is_array($value)){
            $sub_res = getAllCells($value);
            $res = array_merge($res, [["<td rowspan='".$sub_res[1]."'>$key</td>", $sub_res[1]]], $sub_res[0]);
            $leaves += $sub_res[1];
        }else{
            $res = array_merge($res, [["<td>$value</td>", 0]]);
            $leaves++;
        }   
    }
    
    return [$res, $leaves];
}

Online Demo

Online UI Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM