We work on a lot of custom web applications for FileMaker solutions varying from custom CMS functionality to third-party API integrations. Recently, I worked on a project that required building an efficient way to manage an ever-changing web navigation system. I put together some nifty recursive PHP functions to handle most of the grunt work and I thought…”I bet there are tons of others out there who could greatly benefit from this…”. So I decided I would document the whole process in a FileMaker PHP Custom Web Menus Tutorial and share with all of you for you to use in your own solutions and web applications. You may download web sample files here, FileMaker solution demo file here.

In this tutorial we are going to explore building a dynamic menu navigation system using the FileMaker PHP API and Custom Web Publishing. This tutorial with carry your through all of the steps of the process to build the framework for such a navigation system.

STEP 1:

First, let’s build our core database table for our menu. We will need a minimum of 4 fields (besides the normal key(s) and audit fields): Menu_Order, Name, Parent_ID and Link.

PHPMenus_Table_Structure

STEP 2:

Next, let’s build the basic php page that will retrieve our menu data.


//Find Menu Data and build array
$menu = $database->newFindCommand('Menu_items');
$menu->addSortRule('Menu_order', 1, FILEMAKER_SORT_ASCEND);
$menuResult = $menu->execute();

if(FileMaker::isError($menuResult)){
//Trap for errors
die(‘Database Error 50: ‘.$menuResult->getMessage());
}else{
$MenuData = $menuResult->getRecords();    //Get all records from query
$i = 0;
foreach($MenuData as $menuItem) {   //For each item in the results, add it to an array
if($menuItem->getField(‘Parent_ID’)){
$parentItem = $menuItem->getField(‘Parent_ID’)-1;
}else{
$parentItem = $menuItem->getField(‘Parent_ID’);
}
$menuItemArray

[$i] = array (
‘ID’ => $menuItem-> getField(‘___MNI’),
‘Name’ => $menuItem->getField(‘Name’),
‘Order’ => $menuItem->getField(‘Menu_order’),
‘Parent’ =>     $parentItem,
‘Link’ => $menuItem->getField(‘Link’),
);
$i++;
}
}

STEP 3:

Let’s parse our data array into JSON to make it a little easier to work with.


$menuJSON = json_encode ($menuItemArray);
$menuJSONArray = json_decode($menuJSON, true);

STEP 4:

Next, Let’s add a function to prepare our array into a multi-dimensional array to create the parent/child relationships.


//Prepare menu array
function prepareMenu($array)
{
$return = array();
//1
krsort($array);
foreach ($array as $k => &$item)
{
if (is_numeric($item['Parent']))
{
$parent = $item['Parent'];
if (empty($array[$parent]['Childs']))
{
$array[$parent]['Childs'] = array();
}
//2
array_unshift($array[$parent]['Childs'],$item);
unset($array[$k]);
}
}
//3
ksort($array);
return $array;
}

STEP 5:

Now that we have our data and we have formatted it properly, the Last step of the process is to build a recursive function to traverse the array and build unordered lists for our menu navigation while nesting additional levels of unordered lists for submenus where necessary.


///RECURSIVE MENU
function buildMenu($array)
{
echo '

    • ‘. “\n”;

 

    • foreach ($array as $item)

 

    • {

 

‘. “\n”;

 

    • }

 

'. "\n";
}

$menu = prepareMenu($menuJSONArray);

//Call the function to build the menu HTML
buildMenu($menu);

This menu, no matter how deep the nested levels go, will always generate the proper HTML code for your menu system. All you need to do is apply your CSS styling and maybe add some jQuery for some slick functionality.