1

I'm having some issues getting a tree menu to work from bottom-up. I already have a script to work from top-down, which works fine.

This is a very simplified version of my table:

+-----+-----------+--------------------+
| uid | parent_id | page_address       |
+-----+-----------+--------------------+
| 1   | 0         | index.php          |
| 2   | 0         | login.php          |
| 3   | 2         | dashboard.php      |
| 4   | 3         | bookings.php       |
| 5   | 3         | documents.php      |
| 6   | 4         | changebookings.php |
| 7   | 4         | activities.php     |
+-----+-----------+--------------------+

The page_address field is unique.

I can work out what page the user is currently on, for example changebookings.php

I would then like a menu to look like this:

login.php
    dashboard.php
    bookings.php
        changebookings.php
        activities.php
    documents.php

However, the closest I've got so far is the following tree:

login.php
    bookings.php
        changebookings.php

As you can see, my script currently only returns the actual parent, and not a list of links currently in the parent.

For those interested, the script I use in total is at the bottom of this post.

Is there any easier way to get the bottom-up tree as required? Many thanks

Phil


EDIT: I've finally got the code to work, for future users who stumble upon this post, I have added the functionality below:

$dataRows = $databaseQuery->fetchAll();     // Get all the tree menu records

$dataRows = $result->fetchAll(PDO::FETCH_ASSOC);

foreach($dataRows as $row)
{
    if($row['link_address']==substr($_SERVER['PHP_SELF'], 1, strlen($_SERVER['PHP_SELF'])-1))
    {
        $startingId = $row['parent_id'];
    }
}

$menuTree = $this->constructChildTree($dataRows, $startingId);


private function constructChildTree(array $rows, $parentId, $nesting = 0)
{
    $menu = array();

    if(!in_array($nesting, $this->nestingData))
    {
        $this->nestingData[] = $nesting;
    }

    foreach($rows as $row)
    {
        if($row['parent_id']==$parentId && $parentId!=0)
        {
            $menu[] = $row['link_address'];

            $newParentId = $this->getNextParent($rows, $row['parent_id']);

            $parentChildren = $this->constructChildTree($rows, $newParentId, ($nesting+1));

            if(count($parentChildren)>0)
            {
                foreach($parentChildren as $menuItem)
                {
                    $menu[] = 'NESTING' . $nesting . '::' . $menuItem;
                }
            }
        }
    }

    return $menu;
}


private function getNextParent($rows, $parentId)
{
    foreach($rows as $row)
    {
        if($row['uid']==$parentId)
        {
            return $row['parent_id'];
        }
    }
}
Phil Cross
  • 9,017
  • 12
  • 50
  • 84
  • [Storing Hierarchical Data in a Database](http://www.sitepoint.com/hierarchical-data-database-2/) – DarkBee Apr 22 '13 at 11:23

2 Answers2

1

Without reading your code you should be doing:

1) Get current page, look at parent ID.

2) Load all with that parent ID.

3) Get next Parent ID using current Parent ID as ID.

4) If new parent ID != 0, goto step 2 passing in the new Parent ID.

Sounds like you just need to edit your script to include ALL pages with the given ID as their parent ID.

MatthewMcGovern
  • 3,466
  • 1
  • 19
  • 19
  • I'll accept this answer as it was helpful towards re-writing the code which eventually made it work as expected! – Phil Cross Apr 22 '13 at 12:16
  • Cool :) I've done something similar in Javascript so I knew the steps but didn't have the time to go through your code and write it! – MatthewMcGovern Apr 22 '13 at 12:23
1
<?PHP
$sql = "SELECT * FROM TABLE WHERE table parent_id=0";
$result = mysql_query($sql);
while($perant_menu = mysql_fetch_array($result))
{
    echo display_child($perant_menu["uid"],$perant_menu["page_address"]);
}

// Recursive function
function display_child($parent_id,$name)
{
    $sql= "SELECT * FROM table where parent_id = $parent_id";
    $result = mysql_query($sql);
    if(mysql_num_rows($result)>0)
    {
        while($menu = mysql_fetch_array($result))
        {
            echo display_child($menu["id"],$menu["page_address"]);
        }
    }
    else
    {
        echo $name;
    }
}
?>
BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • Unfortunately I couldn't use this code as it uses deprecated mysql* functionality. Also, I'm trying to limit the number of SQL queries made to the server, which unfortunately with this answer, for each parent to retrieve another query would be sent though. I appreicate the time it took to response though :) – Phil Cross Apr 22 '13 at 12:21