2

What is an efficient way to put the tree data into an array?

I followed the sitepoint tutorial to retrieve the tree data.

However, the tutorial only shows how to output the tree, not how to make a multidementional array.

I used

SELECT title, lft, rgt FROM tree_structure WHERE lft BETWEEN $parentLft  AND $parentRgt ORDER BY lft ASC

So for each item, I have its title, left and right values.

I am stuck on making the array look like this

Array
(
 Title: Main Topic
 Children => Array
             (
              => Title: subTopic
                     Leaf:  true
              => Title: Another subtopic
                     Children =>  Array
                               (
                                => Title: subtopic child
                                  Leaf: true
                               )
              ) 

)

If you could help, I would really appreciate it.

PS. The sql output looks like this (except I have title, not name and don't use category_id ):

+-------------+----------------------+-----+-----+
| category_id | name                 | lft | rgt |
+-------------+----------------------+-----+-----+
|           1 | ELECTRONICS          |   1 |  20 |
|           2 | TELEVISIONS          |   2 |   9 |
|           3 | TUBE                 |   3 |   4 |
|           4 | LCD                  |   5 |   6 |
|           5 | PLASMA               |   7 |   8 |
|           6 | PORTABLE ELECTRONICS |  10 |  19 |
|           7 | MP3 PLAYERS          |  11 |  14 |
|           8 | FLASH                |  12 |  13 |
|           9 | CD PLAYERS           |  15 |  16 |
|          10 | 2 WAY RADIOS         |  17 |  18 |
2
  • And how do the records of that query look like? Commented Sep 24, 2009 at 18:45
  • @Gumbo, I use the data from another article for my example. The main thing is that this algorithm uses left and right values to order data. Commented Sep 24, 2009 at 19:04

3 Answers 3

6
+250

Give this code a shot. $results is the database results. $tree is the array you're getting back.

function create_tree ($results) {

    $return = $results[0];
    array_shift($results);

    if ($return['lft'] + 1 == $return['rgt'])
        $return['leaf'] = true;
    else {
        foreach ($results as $key => $result) {
            if ($result['lft'] > $return['rgt']) //not a child
                break;
            if ($rgt > $result['lft']) //not a top-level child
                continue;
            $return['children'][] = create_tree(array_values($results));
            foreach ($results as $child_key => $child) {
                if ($child['rgt'] < $result['rgt'])
                    unset($results[$child_key]);
            }
            $rgt = $result['rgt'];
            unset($results[$key]);
        }
    }

    unset($return['lft'],$return['rgt']);
    return $return;

}
$tree = create_tree($results);
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for your help but the array it made wasn't all right i will try to post the output once i have figure this out
The array returned this this function is not correct and some rows repeat.
This worked, thanks a lot. At first, I had a diff query and got bad results but when I fixed the query, it worked. Thanks!
4

I would start from rewriting the SQL query to this:

SELECT title, (SELECT TOP 1 title 
               FROM tree t2 
               WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt    
               ORDER BY t2.rgt-t1.rgt ASC) AS parent
FROM tree t1
ORDER BY rgt-lft DESC

This will give you result like this:

title                | parent
----------------------------------------------
ELECTRONICS          | NULL
PORTABLE ELECTRONICS | ELECTRONICS
TELEVISIONS          | ELECTRONICS
MP3 PLAYERS          | PORTABLE ELECTRONICS
FLASH                | MP3 PLAYERS
CD PLAYERS           | PORTABLE ELECTRONICS
2 WAY RADIOS         | PORTABLE ELECTRONICS
TUBE                 | TELEVISIONS
LCD                  | TELEVISIONS
PLASMA               | TELEVISIONS

With this, it is much easier.

1 Comment

Thanks for posting this. I've been looking for an SQL script to add a particular ancestor ID (not parent in my case) and it was very easy to solve using your code as a starting point.
0

using the create_tree i got an error at this point:

if ($rgt > $result['lft']) //not a top-level child  continue;

The error it return says: Undefined variable: rgt

Also it did not return the correct number of array..... I am using the same database structure in

http://articles.sitepoint.com/article/hierarchical-data-database/2

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.