tags:

views:

258

answers:

3

I am trying to convert a multi-level array to a table. However my code does not output what I want. It shows the last child, but not other child and grandchild.

I appreciate your help.

DB table

CREATE TABLE IF NOT EXISTS `menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `shortdesc` varchar(255) NOT NULL,
  `status` enum('active','inactive') NOT NULL,
  `parentid` int(11) NOT NULL,
  `order` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=71 ;

--
-- Dumping data for table `menus`
--

INSERT INTO `menus` (`id`, `name`, `shortdesc`, `status`, `parentid`, `order`) VALUES
(24, 'Main menu', 'mainmenu', 'active', 0, 0),
(25, 'Galleri 1', 'galleri1', 'active', 0, 0),
(69, 'Main 2-2', '', 'active', 62, 0),
(68, 'Main 2-1', '', 'active', 62, 0),
(65, 'Main 4', '', 'active', 24, 0),
(64, 'Main 3', '', 'active', 24, 0),
(67, 'Main 1-2', '', 'active', 59, 0),
(62, 'Main 2', '', 'active', 24, 0),
(59, 'Main 1', '', 'active', 24, 0),
(66, 'Main 1-1', '', 'active', 59, 0),
(70, 'Manu 4-1', '', 'active', 65, 0);

View

if (count($navlist)){
  echo "<table border='1' cellspacing='0' cellpadding='3' width='800'>\n";
    echo "<thead>\n<tr valign='top'>\n";
    echo "<th>ID</th>\n<th>Name</th><th>Status</th><th>parentid</th><th>Actions</th>\n";
    echo "</tr>\n</thead>\n<tbody>\n";
     foreach ($navlist as $key => $menu){
     echo "<tr valign='top'>\n";
     echo "<td>".$menu['id']."</td>\n";
     echo '<td><a href="'. site_url(). '/admin/menus/submenus/' . $menu['id'] . '">' .$menu['name']."</a></td>\n";
     echo "<td align='center'>".$menu['status']."</td>\n";
     echo "<td align='center'>".$menu['parentid']."</td>\n";
     echo "<td align='center'>";
     echo anchor('admin/menus/editMenu/'.$menu['id'],'edit');
     echo " | ";
     echo anchor('admin/menus/deleteMenu/'.$menu['id'],'delete', array('class' => 'delete_link'));
     echo "</td>\n";
     echo "</tr>\n";
     if (count($menu['children'])){

     foreach ($menu['children'] as $subkey => $submenu){
     echo "<tr class='child' valign='top'>\n";
     echo "<td>".$submenu['id']."</td>\n";
     echo '<td><a href="'. site_url(). '/admin/menus/submenus/' . $submenu['id'] . '">' .$submenu['name']."</a></td>\n";
     echo "<td align='center'>".$submenu['status']."</td>\n";
     echo "<td align='center'>".$submenu['parentid']."</td>\n";
     echo "<td align='center'>";
     echo anchor('admin/menus/editMenu/'.$submenu['id'],'edit');
     echo " | ";
     echo anchor('admin/menus/deleteMenu/'.$submenu['id'],'delete', array('class' => 'delete_link'));
     echo "</td>\n";
     echo "</tr>\n";
     }
     if (count($submenu['children'])){
     foreach ($submenu['children'] as $subkey => $subsubname){
     echo "<tr class='grandchild' valign='top'>\n";
     echo "<td>". $subsubname['id']."</td>\n";
     echo '<td><a href="'. site_url(). '/admin/menus/submenus/' .  $subsubname['id'] . '">' . $subsubname['name']."</a></td>\n";
     echo "<td align='center'>". $subsubname['status']."</td>\n";
     echo "<td align='center'>". $subsubname['parentid']."</td>\n";
     echo "<td align='center'>";
     echo anchor('admin/menus/editMenu/'. $subsubname['id'],'edit');
     echo " | ";
     echo anchor('admin/menus/deleteMenu/'. $subsubname['id'],'delete', array('class' => 'delete_link'));
     echo "</td>\n";
     echo "</tr>\n";
     }
     }
     }
     }
     echo "</tbody>\n</table>";
     }

HTML Output

<table border='1' cellspacing='0' cellpadding='3' width='800'>
<thead>
<tr valign='top'>
<th>ID</th>
<th>Name</th><th>Status</th><th>parentid</th><th>Actions</th>
</tr>
</thead>
<tbody>
<tr valign='top'>

<td>24</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/24"&gt;Main menu</a></td>
<td align='center'>active</td>
<td align='center'>0</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/24"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/24" class="delete_link">delete</a></td>
</tr>
<tr class='child' valign='top'>
<td>65</td>

<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/65"&gt;Main 4</a></td>
<td align='center'>active</td>
<td align='center'>24</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/65"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/65" class="delete_link">delete</a></td>
</tr>
<tr class='child' valign='top'>
<td>64</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/64"&gt;Main 3</a></td>

<td align='center'>active</td>
<td align='center'>24</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/64"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/64" class="delete_link">delete</a></td>
</tr>
<tr class='child' valign='top'>
<td>62</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/62"&gt;Main 2</a></td>
<td align='center'>active</td>

<td align='center'>24</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/62"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/62" class="delete_link">delete</a></td>
</tr>
<tr class='child' valign='top'>
<td>59</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/59"&gt;Main 1</a></td>
<td align='center'>active</td>
<td align='center'>24</td>

<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/59"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/59" class="delete_link">delete</a></td>
</tr>
<tr class='grandchild' valign='top'>
<td>67</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/67"&gt;Main 1-2</a></td>
<td align='center'>active</td>
<td align='center'>59</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/67"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/67" class="delete_link">delete</a></td>

</tr>
<tr class='grandchild' valign='top'>
<td>66</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/66"&gt;Main 1-1</a></td>
<td align='center'>active</td>
<td align='center'>59</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/66"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/66" class="delete_link">delete</a></td>
</tr>
<tr valign='top'>

<td>25</td>
<td><a href="http://127.0.0.1/ci/index.php/admin/menus/submenus/25"&gt;Galleri 1</a></td>
<td align='center'>active</td>
<td align='center'>0</td>
<td align='center'><a href="http://127.0.0.1/ci/index.php/admin/menus/editMenu/25"&gt;edit&lt;/a&gt; | <a href="http://127.0.0.1/ci/index.php/admin/menus/deleteMenu/25" class="delete_link">delete</a></td>
</tr>
</tbody>
</table>
A: 

You need to implement a recursive function or use a function like array_map with a callback function to process multi-array while sending back appropriate data, you can see more info about that function at php.net site.

Sarfraz
+1  A: 

This solution involves recursion. If you are not familiar with the term or have a hard time following along, please refer to this IBM entry entitled "Mastering recursive programming" to familiarize yourself. It seems as though you only plan on having three levels of navigation. With that being said, this code only handles the classnames parent/child/grandchild for those three levels. You can easily add more by adding new array entries to $depthClassMapping.

/**
 * @param array $level The current navigation level array
 * @param string $output The output to be added to
 * @param int $depth The current depth of the tree to determine classname
 */
function generateRowsByLevel($level, &$output, $depth = 0) {

    $depthClassMapping = array(0 => 'parent', 1 => 'child', 2 => 'grandchild');

    foreach ($level as $row) {
        $output .= "<tr class=\"" . $depthClassMapping[$depth] . "\" valign='top'>\n";
        $output .= "<td>". $row['id']."</td>\n";
        $output .= '<td><a href="'. site_url(). '/admin/menus/submenus/' .  $row['id'] . '">' . $row['name']."</a></td>\n";
        $output .= "<td align='center'>". $row['status']."</td>\n";
        $output .= "<td align='center'>". $row['parentid']."</td>\n";
        $output .= "<td align='center'>";
        $output .= anchor('admin/menus/editMenu/'. $row['id'],'edit');
        $output .= " | ";
        $output .= anchor('admin/menus/deleteMenu/'. $row['id'],'delete', array('class' => 'delete_link'));
        $output .= "</td>\n";
        $output .= "</tr>\n";

        // if the row has any children, parse those to ensure we have a properly 
        // displayed nested table
        if (!empty($row['children'])) {
            generateRowsByLevel($row['children'], $output, $depth + 1);
        }
    }
}

//==================
// RUN THE GENERATOR 
//==================
if (count($navlist)){

    // begin table
    $output = "<table border='1' cellspacing='0' cellpadding='3' width='800'>\n";
    $output .= "<thead>\n<tr valign='top'>\n";
    $output .= "<th>ID</th>\n<th>Name</th><th>Status</th><th>parentid</th><th>Actions</th>\n";
    $output .= "</tr>\n</thead>\n<tbody>\n";

    // generate all table rows
    generateRowsByLevel($navlist, $output);

    // close up the table
    $output .= "</tbody>\n</table>";

    // display table
    echo $output;
}
cballou
I changed += to .= and $depthClasMapping[$depth] to $depthClassMapping[$depth]. then it works. Thanks.
shin
I must've been thinking about javascript this morning with the `+=`
cballou
A: 

Your logic is too flat and flawed. Make use of functions and recursion. You may find this blog useful as well: http://crisp.tweakblogs.net/blog/317/formatting-a-multi-level-menu-using-only-one-query.html

BalusC