PHP Recursive Function to Build a Site Tree / Site Map

A problem faced fairly regularly is the need to generate a site tree either for a menu or a site map.

Assuming your page structure in your database is along the lines of:

intPageId strPageName intParentId
1 Top Level Page X 0
2 Top Level Page Y 0
3 Child Page X 1
4 Grandchild Page X 3
5 Grandchild Page Y 3

Giving you a visual structure of:

Site tree structure

I’m a developer, not a designer. Don’t judge me

You can achieve this fairly simply in with the following PHP recursive function to get your page structure into an array. Note, I have used the Laravel query builder in this example as the project I wrote this for was a Laravel project, but this can be swapped out with a query builder from whatever framework you are using or with PHP’s PDO (or any of the lesser PHP APIs for working with databases).

function generateSiteTree($startAt)
{
	if ($children = \DB::table('cms_pages')->where('intParentId', '=', $startAt)->get())
	{
		$thisLevel = array();
		foreach ($children as $child) 
		{
			$thisLevel[$child->intPageId] = $child;
			$thisLevel[$child->intPageId]->children = generateSiteTree($child->intPageId);
		}
		return $thisLevel;
	}
 
}
 
$tree = generateSectionSiteTree(0);
 
 
print_r($tree);

That’s it.

Bonus recursive function

The project I wrote this function for required me to be able to reel off the site tree only for the top level parent of the current page, regardless of however deep you currently are.

This is easily achieved with this function:

function recurseToFindSectionParent($pageId)
{
	$current = \DB::table('cms_pages')->where('intPageId', '=', $pageId)->first();
 
	if ($current->intParentId == 0) //we've reached the top of the chain
	{
		return $current->intPageId;
	}
	else //keep going
	{
		return recurseToFindSectionParent($current->intParentId);
	}
}
$topParentID = recurseToFindSectionParent($currentPageId);

You can now feed the ID of the top level parent into the generateSiteTree function:

$tree = generateSiteTree($topParentID);
Did you like this post? Why not subscribe?

Leave a Reply

Your email address will not be published. Required fields are marked *