Normally, this task would require creating a huge and complex array of items to create the menu structure. This class simplifies that process and doesn't require you to use any arrays.
It also obviously supports multi-level lists, perfect for creating drop-down navigation menus.
// Include necessary classes
include 'menu.class.php';
include 'tidy_menu.class.php';
// Build out menu structure, the syntax makes it easy to see the levels
$menu = menu::factory()
->add('About Us', 'about-us.php', menu::factory()
->add('Who We Are', 'who-we-are.php')
->add('What We Do', 'what-we-do.php')
->add('Other Things', 'other-things.php'))
->add('Random', 'random.php', menu::factory()
->add('Link One', 'link-one.php')
->add('Link Two', 'link-two.php', menu::factory()
->add('Level Three', 'level-three.php')));
// (optional) Add some attributes to the main list
$menu->attrs = array
(
'id' => 'navigation',
'class' => 'menu',
);
/*
You can also do the following instead
$menu->id = 'navigation';
$menu->class = 'menu';
*/
// (optional) Tell it the current active item
$menu->current = 'level-three.php';
/*
Echo the menu
Normally, you could just do this:
echo $menu;
But for this example, we're using the tidy_menu class to output nice, readable HTML,
whereas just echoing normally would render the HTML in a single line.
*/
echo new tidy_menu($menu);
The above generates the following HTML:
<ul id="navigation" class="menu"> <li class="parent"><a href="about-us.php">About Us</a> <ul> <li><a href="who-we-are.php">Who We Are</a></li> <li><a href="what-we-do.php">What We Do</a></li> <li><a href="other-things.php">Other Things</a></li> </ul> </li> <li class="parent active"><a href="random.php">Random</a> <ul> <li><a href="link-one.php">Link One</a></li> <li class="parent active"><a href="link-two.php">Link Two</a> <ul> <li class="active current"><a href="level-three.php">Level Three</a></li> </ul> </li> </ul> </li> </ul>
Here's a menu with some CSS applied.
There are a few different ways to go about creating your menus. Here are a few examples.
echo menu::factory()
->add('Item One', 'item_one.php')
->add('Item Two', 'item_two.php', menu::factory()
->add('Item Three', 'item_three.php')
->add('Item Four', 'item_four.php'));
$attrs = array('class' => 'my_menu');
$active = 'item_one.php';
echo menu::factory()
->add('Item One', 'item_one.php')
->add('Item Two', 'item_two.php')
->render($attrs, $active);
Or if you find it easier to create the array yourself, like if you were pulling values from a database, you can do that and just pass in the array to the class.
$menu = array
(
array
(
'title' => 'Item One',
'url' => 'item_one.php',
),
array
(
'title' => 'Item Two',
'url' => 'item_two.php',
'children' => array
(
array
(
'title' => 'Item Three',
'url' => 'item_three.php',
),
array
(
'title' => 'Item Four',
'url' => 'item_four.php',
)
)
)
);
$attrs = array('id' => 'menu');
$active = $_SERVER['REQUEST_URI'];
echo menu::factory($menu)->render($attrs, $active);
Below is an example of using this class with a database that holds your menu structure.
The table structure could look something like this:
menu +--------+---------+ | id | int(11) | +--------+---------+ | title | varchar | +--------+---------+ | url | varchar | +--------+---------+ | parent | int(11) | +--------+---------+
Then, in your model file you could have a function like this:
public function build($level = NULL)
{
$level_id = empty($level) ? 0 : $level->id;
$level = $this->where('parent', $level_id)->orderby('id', 'asc')->find_all();
$menu = new menu;
foreach ($level as $lvl)
{
$menu->add($lvl->title, $lvl->url, $this->build($lvl));
}
return $menu;
}
And then in your controller or view, you could do this to render the menu:
echo ORM::factory('menu')->build()->render();