Welcome to the wonderful world of recursion!
See also What is recursion and when should I use it?
What you need is a function that can call itself with a subset or refined set of variables.
This sounds more difficult than it really is. You need to call the same function multiple times and using it's return output as a variable inside itself.
<?php
# Recursive function to show each category and sub-categories
function showCategory( $category, $offset = 0 ) {
$html = '';
# Open the column
if ( $offset > 0 ) {
$html .= '<td style="margin-left: ' . $offset . 'px; padding-left: ' . $offset . 'px;">';
$html .= '<span>';
} else {
$html .= '<td>';
}
$html .= $category['name'];
if ( isset( $category['sub_categories'] ) ) {
foreach ( $category['sub_categories'] as $sub_category ) {
# Wrap table around the results
$html .= '<table>';
# Add 50 pixels to each recursion - call this function with sub_category as parameter
$html .= showCategory( $sub_category, $offset + 50 );
$html .= '</table>';
}
}
if ( $offset > 0 ) {
$html .= '</span>';
}
# Close the column
$html .= '</td>';
# Return the row
return '<tr>' . $html . '</tr>';
}
# Test data:
$categories = [
[
'name' => 'foo',
'sub_categories' => [
['name' => 'sub1'],
[
'name' => 'sub2',
'sub_categories' => [
['name' => 'subsub1'],
['name' => 'subsub2']
]
]
]
]
];
# This is where we show stuff
foreach ( $categories as $category ) {
echo showCategory( $category );
}