PHP Classes: Navigation Menu Handler

Whenever I am tasked with building a dynamic website with multiple levels of (dynamic) hierarchical navigation I tend to use this class (or a variation of it) for handling the navigation. Note - this class requires PHP 5 or later.

The structure of how the navigation items are stored in the database is important for people wanting to use this class. Basically, all nav items should be stored in the same database table with a ‘parent id’ field defined which refers to the primary id of the record which is its parent. I like to make top level nav items have a parent id of 0.

An example of what the nav table should look like is as shown below via an SQL script:

CREATE TABLE Pages (
PageID INT NOT NULL AUTO_INCREMENT,
URI VARCHAR(250),
MenuText VARCHAR(100) NOT NULL,
ParentID INT NOT NULL DEFAULT 0,
PRIMARY KEY(PageID)
);

No foreign key reference from the ParentID to the PageID is enforced here because the top level nav items reference zero and not existing records in the table. You may however choose to add an index to the ParentID field. Also, on a side note, I like to also store the URI the page uses too, depending on my site setup which is why I have included it here.

The full basic version of the class, which is dependent upon the DB table structure above is as follows:

+ –

Menu Navigation Handler Class:

<?php
require_once 'dbconnect.php'; //include DB connect class
class NavHandler
{
/*customize*/
//database table which holds the nav items
private $menu_table = "Pages";
//db table field that uniquely identifies the record
private $identifier = "PageID";
//field in the db which references the parent id
private $parent_id_field = "ParentID";
private $top_level_parent_id = 0;
/***/

//publically available breadcrumbs array if page ids
public $CurrentMenuIDs = array();

private $DB; //DB connection var

public function __construct($current_id)
{
$this->DB = new DatabaseConnection();
$this->set_current_ids($current_id);
}

//sets CurrentMenuIDs array with all current menu ids. array key is menu level.
private function set_current_ids($page_id)
{
while($page_id != $this->top_level_parent_id)
{
$menu_dataset = $this->DB->ExecuteSelectQueryRow("SELECT * FROM $this->menu_table WHERE $this->identifier = $page_id");
array_push($this->CurrentMenuIDs, $page_id);
$page_id = $menu_dataset[$this->parent_id_field];
}
//first element is [0] = 0 to keep keys consistent with menu level
array_push($this->CurrentMenuIDs, 0);
$this->CurrentMenuIDs = array_reverse($this->CurrentMenuIDs);
}

//gets the menu items for the specified level passed as parameter (main/top menu is level 1)
public function get_menu_items($menu_level = 1)
{
//current page level must be no more than one level higher than the menu level requested
$level_ok = $this->check_requested_level($menu_level);

if($level_ok)
{
if($menu_level == 1)
$parent_id = $this->top_level_parent_id;
else
{
$parent_level = $menu_level - 1;
$parent_id = $this->CurrentMenuIDs[$parent_level];
}

$menu_dataset = $this->DB->ExecuteSelectQuerySet("SELECT * FROM $this->menu_table WHERE $this->parent_id_field = $parent_id");

if(count($menu_dataset) > 0)
return $menu_dataset;
else
return false;
}
else
return false;
}

//current page level must be no more than one level higher than the menu level requested, because then we have no parent id to use for the requested menu
private function check_requested_level($requested_level)
{
end($this->CurrentMenuIDs); //set internal array pointer to the last element which is the current page
$current_level = key($this->CurrentMenuIDs); //level of the current page = array key of last element
$max_level_allowed = $current_level + 1;

if($requested_level <= $max_level_allowed)
return true;
else
return false;
}
}
?>
Comments (0)
+ –