1

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?

2
  • How dynamic does this need to be? Do we need to see a differently populated array and the desired result so that we can reverse engineer the logic? Commented Jul 19, 2022 at 11:14
  • the number of columns is fix (3), but the number auf rows is arbitrary Commented Jul 19, 2022 at 11:22

1 Answer 1

1
  • 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 0th index being the td rows and 1st 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 tds'. 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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.