Building an Extensible Menu Class - Saving My Bookmarks (
Page 7 of 10 )
At this stage, I
think I have enough building blocks to actually begin using this class to build
menu trees. Keep in mind, though, that I've been wrong before, and so my initial
feeling of satisfaction may soon disappear.
The only way to find out for
sure is to try building a tree to see if the methods exposed by the class are
simple and generic enough to be used in a variety of situations - so let's do
that. I will attempt to use this Menu class to build a simple Web portal, which
has links classified into hierarchical categories (a lot like the Open Directory
Project at http://www.dmoz.org/)
This is a good time to download the
accompanying source code, which contains complete versions of the SQL records
displayed below, together with a copy of the final Menu class.
menu.zipSince this is a portal, my database needs to
reflect the various categories and links. Here's a snippet:
mysql> SELECT id, link, label, parent FROM menu3;
+----+-------------------------------------+----------------+--------+
| id | link | label | parent |
+----+-------------------------------------+----------------+--------+
| 1 | | Server Side | 0 |
| 2 | | Client Side | 0 |
| 3 | | Tools | 0 |
| 4 | | DevTalk | 0 |
| 5 | http://www.devshed.com/ClipScripts/ | ClipScripts | 0 |
| 6 | http://www.devshed.com/rdf.html | DevShed RDF | 0 |
| 7 | http://www.devshed.com/Propaganda | Propaganda! | 0 |
| 8 | http://www.ngenuity.com/advertise/ | About DevShed | 0 |
| 9 | | Administration | 1 |
+----+-------------------------------------+----------------+--------+
My user interface should clearly reflect this menu tree, by
making a distinction between "categories" and "links". A click on a category
reveals the sub-categories and links under it, while a click on a link directs
the browser to the appropriate content module or URL.
Here's the script
to accomplish this:
<?
// set default id to 0
if (!$id) { $id = 0; }
// include class
include("menu.class.php");
// create Menu
$obj = new Menu;
// get next level
$children = $obj->get_children($id);
// check to see if items are "leaves" or "branches" on the tree
for ($x=0; $x<sizeof($children); $x++)
{
if($obj->get_type($children[$x]["id"]) == 1)
{
$branches[] = $children[$x];
}
else
{
$leaves[] = $children[$x];
}
}
// get lineage from tree root (used to create navigation path)
$ancestors = $obj->get_ancestors($id)
?>
<html>
<head>
<basefont face="Arial">
</head>
<body bgcolor="White" link="Black" vlink="Black">
<img src="logo.gif" height=50 width=206 border=0 alt="">
<table width="100%" border="0" cellspacing="0" cellpadding="3"
bgcolor="#9898D0">
<tr>
<td height=20>
<font color="Black"><b>
<?
// use $ancestors[] to set up path
for ($x=0; $x<sizeof($ancestors); $x++)
{
$path .= "<a href=" . $PHP_SELF . "?id=" . $ancestors[$x]["id"] . ">" .
$ancestors[$x]["label"] . "</a>" . " > ";
}
// add current level to path and print
$path .= $obj->get_label($id);
echo $path;
?>
</b></font>
</td>
<td align=right><? if ($id > 0) { ?><font color="Black"><b><a href="<? echo
$PHP_SELF; ?>">Top</a></b></font> <? } ?></td>
</tr>
</table>
<p>
<?
if ($branches)
{
?>
<b><font color="#9898D0" size="+1">Categories</font></b>
<ul>
<?
// print branches here
for ($x=0; $x<sizeof($branches); $x++)
{
echo "<li><a href=" . $PHP_SELF . "?id=" . $branches[$x]["id"] . ">" .
$branches[$x]["label"] . "</a><br>";
}
?>
</ul>
<?
}
?>
<p>
<?
if ($leaves)
{
?>
<b><font color="#9898D0" size="+1">Links</font></b>
<ul>
<?
// print leaves here
for ($x=0; $x<sizeof($leaves); $x++)
{
echo "<li><a href=" . $leaves[$x]["link"] . ">" . $leaves[$x]["label"] .
"</a><br>";
}
?>
</ul>
<?
}
?>
</body>
</html>
In this case, I'm first using the get_children() method to
obtain a list of all items under the current tree branch. I'm then using the
get_type() method to split the list of child nodes into two separate arrays,
$branches and $nodes, and formatting and displaying each appropriately. Finally,
with the help of the get_ancestors() method, I'm building a hierarchical,
clickable trail leading to the current node - just like any good portal
would.
Here's what the end result looks like: