1

So I have an associative array that's been passed via JQuery to my PHP page that contains the structure of a menu. This effectively comes in as something like this:

[{"id":1,"children":[{"id":2,"children":[{"id":3},{"id":4}]},{"id":5}]}]

I've decoded the string and made it into an associative array using json_decode like so:

$cleanJSON = json_decode($JSON,true);

This is all fine so far and gives the result like this:

Array (
            [0] => Array
                (
                    [id] => 1
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 2
                                    [children] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [id] => 3
                                                )
                                            [1] => Array
                                                (
                                                    [id] => 4
                                                )
                                        )
                                )
                            [1] => Array
                                (
                                    [id] => 5
                                )
                        )
                )
        )

The problem I'm having is I now need to figure out the left and right nested set values of each item so that I can update my database with this new structure.

The reason I'm doing this is to allow me to accomplish reordering menu items within the nested set model.

Getting a resulting array which looks something like the below example would be perfect:

Array (
        [0] => Array
            (
                [id] => 1
                [left] => 1
                [right] => 10
            )
        [1] => Array
            (
                [id] => 2
                [left] => 2
                [right] => 7
            )
        [2] => Array
            (
                [id] => 3
                [left] => 3
                [right] => 4
            )
        [3] => Array
            (
                [id] => 4
                [left] => 5
                [right] => 6
            )
        [4] => Array
            (
                [id] => 5
                [left] => 8
                [right] => 9
            )
    )

The below code is a mess and doesn't work at all, but it's as far as I got with it:

$i_count = 1;
$i_index = 1;
$a_newTree;

function recurseTree($nestedSet) 
{
    global $i_count;
    global $a_newTree;

    $i_left = $i_count;
    $a_newTree[$i_count-1]['left'] = $i_left;
    $i_count++;

    foreach ($nestedSet AS $key => $value)  
    {               
        if ($value['children']) 
          {
              foreach($value['children'] as $a_child)  
              {
                  recurseTree($a_child);      // traverse
              }
          }
    }   

    $i_right=$i_count; // right = count
    $a_newTree[$i_count-1]['right'] = $i_right; 
        $i_count++;        // count+1   
}

Any help appreciated!

2 Answers 2

2

SOLVED!

A nifty little function created by a friend has solved this issue for me. He actually created it in Javascript but I've translated it over to PHP. I'll supply both below.

The PHP Version first:

$JSON = '[{"id":1,"children":[{"id":2,"children":[{"id":3},{"id":4}]},{"id":5}]}]';
$cleanJSON = json_decode($JSON,true);

$a_newTree = array();       

function recurseTree($structure,$previousLeft) 
{
    global $a_newTree;  // Get global Variable to store results in.

    $indexed = array();                     // Bucket of results.       
    $indexed['id'] = $structure['id'];      // Set ID
    $indexed['left'] = $previousLeft + 1;   // Set Left

    $lastRight = $indexed['left'];

    $i_count = 0;
    if ($structure['children'])
    {
        foreach ($structure['children'] as $a_child)
        {
            $lastRight = recurseTree($structure['children'][$i_count],$lastRight);
            $i_count++;
        }
    }

    $indexed['right'] = $lastRight + 1;     // Set Right

    array_push($a_newTree,$indexed);        // Push onto stack

    return $indexed['right'];       
}

recurseTree($cleanJSON[0],0);
print_r($a_newTree);

Fantastic little function outputs the exact array required.

OK, For the original JAVASCRIPT version my friend wrote, see below:

<html>
   <head>
      <title>Experiment</title>
      <script type="text/javascript">
         /* initial structure */
         var struct = [
            {
                "id": 1,
                "children": [{
                    "id": 2,
                    "children": [{
                        "id": 3
                    }, {
                        "id": 4
                    }]
                }, {
                    "id": 5
                }]
            }
         ];

         function experiment() {
            /* stores all results */
            var all = [];

            /* kick off the recursive method */
            handleNode(struct[0], 0, all);

            /* print the results to browser debugger console*/
            console.log(all);
         }

         function handleNode(node, previousLeft, all) {
            /* create and store the new entry (bucket to put left, right, and id ) */
            var indexed = {};
            all.push(indexed);

            indexed.id = node["id"];
            indexed.left = previousLeft + 1;

            var lastRight = indexed.left;
            /* here we do the recursion for every child */
            for (var x in node["children"]) {
               lastRight = handleNode(node["children"][x], lastRight, all);
            }

            /* once all children have been iterated over we can store the rigth */
            indexed.right = lastRight + 1;

            /* return the newly updated right for this bucket */
            return indexed.right;
         }

         /* run the experiment */
         experiment();

      </script>
   </head>
   <body>

   </body>
</html>

Using Google Chrome you can see the results in the Console window. (CTRL-SHIFT-i).

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

Comments

0

I wouldn't try to code a Nested Set implementation yourself, there are versions available you can use:

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.