1

I have a query SELECT * FROM NavigationMenu ORDER BY parentNavigationMenuId ASC, navigationOrder ASC that will return an array of nav objects. The result i have to work with looks like this:

array (
  0 => 
  array (
    'navigationMenuId' => '1',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Home',
    'navigationOrder' => '1',
    'subNavigationItems' => 
    array (
    ),
  ),
  1 => 
  array (
    'navigationMenuId' => '2',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/top-nav-1/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Top Nav 1',
    'navigationOrder' => '2',
    'subNavigationItems' => 
    array (
    ),
  ),
  2 => 
  array (
    'navigationMenuId' => '3',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/top-nav-2/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Index',
    'navigationAnchor' => 'Top Nav 2',
    'navigationOrder' => '3',
    'subNavigationItems' => 
    array (
    ),
  ),
  3 => 
  array (
    'navigationMenuId' => '8',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/top-nav-3/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 3',
    'navigationAnchor' => 'Top Nav 3',
    'navigationOrder' => '4',
    'subNavigationItems' => 
    array (
    ),
  ),
  4 => 
  array (
    'navigationMenuId' => '9',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/top-nav-4/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 4',
    'navigationAnchor' => 'Top Nav 4',
    'navigationOrder' => '5',
    'subNavigationItems' => 
    array (
    ),
  ),
  5 => 
  array (
    'navigationMenuId' => '13',
    'parentNavigationMenuId' => '0',
    'fullURL' => '/top-nav-5/index',
    'contentSlug' => 'index',
    'contentAlias' => 'Top Nav 5',
    'navigationAnchor' => 'Top Nav 5',
    'navigationOrder' => '6',
    'subNavigationItems' => 
    array (
    ),
  ),
  6 => 
  array (
    'navigationMenuId' => '4',
    'parentNavigationMenuId' => '3',
    'fullURL' => '/top-nav-2/sub-nav-1',
    'contentSlug' => 'sub-nav-1',
    'contentAlias' => 'Sub Nav 1',
    'navigationAnchor' => 'Sub Nav 1',
    'navigationOrder' => '1',
    'subNavigationItems' => 
    array (
    ),
  ),
  7 => 
  array (
    'navigationMenuId' => '5',
    'parentNavigationMenuId' => '3',
    'fullURL' => '/top-nav-2/sub-nav-2',
    'contentSlug' => 'sub-nav-2',
    'contentAlias' => 'Sub Nav 2',
    'navigationAnchor' => 'Sub Nav 2',
    'navigationOrder' => '2',
    'subNavigationItems' => 
    array (
    ),
  ),
  8 => 
  array (
    'navigationMenuId' => '6',
    'parentNavigationMenuId' => '3',
    'fullURL' => '/top-nav-2/sub-nav-3',
    'contentSlug' => 'sub-nav-3',
    'contentAlias' => 'Sub Nav 3',
    'navigationAnchor' => 'Sub Nav 3',
    'navigationOrder' => '3',
    'subNavigationItems' => 
    array (
    ),
  ),
  9 => 
  array (
    'navigationMenuId' => '7',
    'parentNavigationMenuId' => '3',
    'fullURL' => '/top-nav-2/sub-nav-4',
    'contentSlug' => 'sub-nav-4',
    'contentAlias' => 'Sub Nav 4',
    'navigationAnchor' => 'Sub Nav 4',
    'navigationOrder' => '4',
    'subNavigationItems' => 
    array (
    ),
  ),
  10 => 
  array (
    'navigationMenuId' => '10',
    'parentNavigationMenuId' => '9',
    'fullURL' => '/top-nav-4/sub-nav-1',
    'contentSlug' => 'sub-nav-1',
    'contentAlias' => 'Sub Nav 1',
    'navigationAnchor' => 'Sub Nav 1',
    'navigationOrder' => '1',
    'subNavigationItems' => 
    array (
    ),
  ),
  11 => 
  array (
    'navigationMenuId' => '11',
    'parentNavigationMenuId' => '9',
    'fullURL' => '/top-nav-4/sub-nav-2',
    'contentSlug' => 'sub-nav-2',
    'contentAlias' => 'Sub Nav 2',
    'navigationAnchor' => 'Sub Nav 2',
    'navigationOrder' => '2',
    'subNavigationItems' => 
    array (
    ),
  ),
  12 => 
  array (
    'navigationMenuId' => '12',
    'parentNavigationMenuId' => '9',
    'fullURL' => '/top-nav-4/sub-nav-3',
    'contentSlug' => 'sub-nav-3',
    'contentAlias' => 'Sub Nav 3',
    'navigationAnchor' => 'Sub Nav 3',
    'navigationOrder' => '3',
    'subNavigationItems' => 
    array (
    ),
  ),
)

Any one of these objects can have child nav items (a child can have other children and so on) which is why each nav item has an empty array of subNavigationItems. I basically want to use the navigationMenuId and parentNavigationMenuId properties and build a json object that has the correct children nested under the correct parents. I'm assuming it could be done with a series of loops for the logic of it is giving me a headache. Anyone have any thoughts on how this can be achieved? Here is an example json of what i would like (or something similar):

    [
        {
            "navigationMenuId": "1",
            "parentNavigationMenuId": "0",
            "fullURL": "/index",
            "contentSlug": "index",
            "contentAlias": "Index",
            "navigationAnchor": "Home",
            "navigationOrder": "1",
            "subNavigationItems": []
        },
        {
            "navigationMenuId": "2",
            "parentNavigationMenuId": "0",
            "fullURL": "/top-nav-1/index",
            "contentSlug": "index",
            "contentAlias": "Index",
            "navigationAnchor": "Top Nav 1",
            "navigationOrder": "2",
            "subNavigationItems": []
        },
        {
            "navigationMenuId": "3",
            "parentNavigationMenuId": "0",
            "fullURL": "/top-nav-2/index",
            "contentSlug": "index",
            "contentAlias": "Index",
            "navigationAnchor": "Top Nav 2",
            "navigationOrder": "3",
            "subNavigationItems": [
                {
                    "navigationMenuId": "4",
                    "parentNavigationMenuId": "3",
                    "fullURL": "/top-nav-2/sub-nav-1",
                    "contentSlug": "sub-nav-1",
                    "contentAlias": "Sub Nav 1",
                    "navigationAnchor": "Sub Nav 1",
                    "navigationOrder": "1"
                },
                {
                    "navigationMenuId": "5",
                    "parentNavigationMenuId": "3",
                    "fullURL": "/top-nav-2/sub-nav-2",
                    "contentSlug": "sub-nav-2",
                    "contentAlias": "Sub Nav 2",
                    "navigationAnchor": "Sub Nav 2",
                    "navigationOrder": "2"
                },
                {
                    "navigationMenuId": "6",
                    "parentNavigationMenuId": "3",
                    "fullURL": "/top-nav-2/sub-nav-3",
                    "contentSlug": "sub-nav-3",
                    "contentAlias": "Sub Nav 3",
                    "navigationAnchor": "Sub Nav 3",
                    "navigationOrder": "3"
                },
                {
                    "navigationMenuId": "7",
                    "parentNavigationMenuId": "3",
                    "fullURL": "/top-nav-2/sub-nav-4",
                    "contentSlug": "sub-nav-4",
                    "contentAlias": "Sub Nav 4",
                    "navigationAnchor": "Sub Nav 4",
                    "navigationOrder": "4"
                }
            ]
        },
        {
            "navigationMenuId": "8",
            "parentNavigationMenuId": "0",
            "fullURL": "/top-nav-3/index",
            "contentSlug": "index",
            "contentAlias": "Top Nav 3",
            "navigationAnchor": "Top Nav 3",
            "navigationOrder": "4",
            "subNavigationItems": []
        },
        {
            "navigationMenuId": "9",
            "parentNavigationMenuId": "0",
            "fullURL": "/top-nav-4/index",
            "contentSlug": "index",
            "contentAlias": "Top Nav 4",
            "navigationAnchor": "Top Nav 4",
            "navigationOrder": "5",
            "subNavigationItems": [
                {
                    "navigationMenuId": "10",
                    "parentNavigationMenuId": "9",
                    "fullURL": "/top-nav-4/sub-nav-1",
                    "contentSlug": "sub-nav-1",
                    "contentAlias": "Sub Nav 1",
                    "navigationAnchor": "Sub Nav 1",
                    "navigationOrder": "1"
                },
                {
                    "navigationMenuId": "11",
                    "parentNavigationMenuId": "9",
                    "fullURL": "/top-nav-4/sub-nav-2",
                    "contentSlug": "sub-nav-2",
                    "contentAlias": "Sub Nav 2",
                    "navigationAnchor": "Sub Nav 2",
                    "navigationOrder": "2"
                },
                {
                    "navigationMenuId": "12",
                    "parentNavigationMenuId": "9",
                    "fullURL": "/top-nav-4/sub-nav-3",
                    "contentSlug": "sub-nav-3",
                    "contentAlias": "Sub Nav 3",
                    "navigationAnchor": "Sub Nav 3",
                    "navigationOrder": "3"
                }
            ]
        },
        {
            "navigationMenuId": "13",
            "parentNavigationMenuId": "0",
            "fullURL": "/top-nav-5/index",
            "contentSlug": "index",
            "contentAlias": "Top Nav 5",
            "navigationAnchor": "Top Nav 5",
            "navigationOrder": "6",
            "subNavigationItems": []
        }
    ]

Please let me know you can think of a better way to handle this than what i am thinking. Thanks!

ryanpitts1
  • 862
  • 1
  • 16
  • 33
  • 1
    possible duplicate of [How can I convert a series of parent-child relationships into a hierarchical tree?](http://stackoverflow.com/questions/2915748/how-can-i-convert-a-series-of-parent-child-relationships-into-a-hierarchical-tre) – jeroen Oct 31 '13 at 21:45

2 Answers2

2

Use objects instead of arrays. In PHP >= 5.0 Objects will be references when assigning them. Then you'll need to loop over the result of these objects and build the navigation tree.

I'd use an item class to encapsulate the logics and providing a toArray() method and a toJson() method which consumes the result of toArray() and passes them to json_encode().

Example:

public function toArray()
{
    $data = array(
        'navigationMenuId' => $this->id,
        // ...
        'subNavigationItems' => array()
    )

    foreach ($this->children as $child) {
        $data['subNavigationItems'][] = $child->toArray();
    }

    return $data;
}

public function toJson()
{
    return json_encode($this->toArray());
}
tux-rampage
  • 108
  • 5
0

Maybe I'm missing something about the format you want, but why not just use json_encode? Does it not produce the correct ouput?

http://php.net/manual/en/function.json-encode.php

$json = json_encode($input);

Oh, never mind, I see in your output you need to move things around the tree. json_encode would be used after generating the correct php array.

Matt
  • 5,478
  • 9
  • 56
  • 95
  • 1
    ryan wants to show a hierarchical object from a two-dimentional array not just get the results into a json string – Popnoodles Oct 31 '13 at 21:46
  • 1
    Yup, I missed that. The answer in the duplicate link above should handle it just fine (just write a recursive function). – Matt Oct 31 '13 at 21:51