HomePHP Page 8 - Building an Extensible Menu Class
Reaching Higher - PHP
So you know the theory behind OOP, but don't really understandits applications? Well, it's time to take objects out of the classroom andinto the real world - this article demonstrates how OOP can save you timeand effort by building a PHP-based Menu object to describe therelationships in a hierarchical menu tree. And since the proof of thepudding is in the eating, it then combines the newly-minted Menu objectwith some of the most popular JavaScript menu systems available online toshow you how cool objects really are.
Now, while that's all fine and dandy, a portal is perhaps the simplest application of this class. It remains to be seen if it can be used with other, more complex menu interfaces. So let's put it to the test, by putting it in the ring with some popular JavaScript-based menu systems.
The first of these is the very popular HIERmenus script (available at http://www.webreference.com/dhtml/hiermenus/ ). This very flexible menu system is completely written in JavaScript, and relies on JavaScript arrays (packaged in a specific format) to build a hierarchical menu tree. I'm not going to get into the nitty-gritty of how it works - there's some excellent documentation if you're interested - but rather plan to focus on how this client-side code can be connected to a database of menu items via the Menu class.
Let's suppose that I wanted to build a menu tree which looked like this:
The downside here is obvious - each time I want to change the
menu structure, I have to go into the JavaScript source and muck about with the arrays (which aren't exactly all that user-friendly to begin with.) What I would prefer to do, however, is somehow interface my database table to the HIERmenus system, so that updating the menu becomes as simple as executing an SQL query to change the relationships in the mySQL table.
With the help of some clever PHP code and the Menu object I've just built, this becomes not just possible, but a snap to accomplish. The first step is to alter the HIERmenus scripts to reference a PHP file for the arrays, rather than a JavaScript file - simply alter the reference to "HM_Arrays.js" in the file "HM_Loader.js" to "HM_Arrays.js.php", as below.
Next, create the script "HM_Arrays.js.php", and populate it
with the following PHP code:
<?
// options to configure menu appearance
$HM_Menu_Options = "150, 200, 50, \"black\", \"white\", \"white\",
\"black\", \"black\", \"gray\", 0, 0, 0, 1, 1, 1, \"null\", \"null\", ,";
// create object
include("menu.class.php");
$obj = new Menu;
// run recursive function
buildMenu(0, "HM_Array1");
// this is a recursive function to generate
// the JS arrays needed by HIERmenus
// this function accepts an id (used to generate children)
// and a prefix string (attached to every array name, needed by HIERmenus)
// for more information on how this works and syntax,
// refer to HIERmenus documentation
function buildMenu($id, $prefix)
{
// obtain a reference to the Menu object
// and also source the options
global $obj;
global $HM_Menu_Options;
// get children of this node
$children = $obj->get_children($id);
// create a JS array with the correct name
$array_str = $prefix . " = [ [" . $HM_Menu_Options . "]";
// iterate through child nodes and create individual array elements
for ($x=0; $x<sizeof($children); $x++)
{
$array_elements_str = ", [\"" . $children[$x]['label'] . "\", \"" .
$children[$x]['link'] . "\", 1, 0, " . $obj->get_type($children[$x]['id'])
. "]";
// if a child node has further children,
// recurse with appropriate modification to the prefix
if($obj->get_type($children[$x]['id']) == 1)
{
$temp = $prefix . "_" . ($x+1);
buildMenu($children[$x]['id'], $temp);
}
// add the final list of array elements to the main array
$array_str .= $array_elements_str;
}
// close the JS array
$array_str .= " ];";
// and print it
print $array_str;
}
?>
The end result of all this processing: a set of JavaScript
arrays containing the various menu nodes, in a format which is acceptable to HIERmenus. This is accomplished by means of a recursive function (conceptually identical to the one used in the print_menu_tree() method) which takes care of iterating through the various levels of the menu tree and printing arrays in the format required by HIERmenus.
Now all we need is a HTML page which activates the HIERmenus system and displays the menu tree in all its glory.
<html>
<head>
<basefont face="Arial">
<script language="JavaScript" type="text/javascript">
<!--
if(window.event + "" == "undefined") event = null;
function HM_f_PopUp(){return false};
function HM_f_PopDown(){return false};
popUp = HM_f_PopUp;
popDown = HM_f_PopDown;
//-->
</script>
</head>
<body>
<a href="#" onMouseOver="popUp('HM_Menu1',event)"
onMouseOut="popDown('HM_Menu1')">Roll your mouse over this link to see a
menu</a>
<script language="JavaScript1.2" src="HM_Loader.js"
type='text/javascript'></script>
</body>
</html>
And here's what it looks like:
Don't worry too much about the JavaScript code in this example - it is merely standard code required for HIERmenus to work, and is clearly documented by the developers of the system. The important thing to note here is that we've taken a pure client-side application and successfully connected it to a server-side database using standard method calls within the Menu object.
Of course, this solution may not be ideal in every case. Using a database and a PHP script to generate the JavaScript arrays dynamically (rather than storing and using arrays from static JavaScript files) may degrade performance; however, it does offer a benefit from the point of view of simpler maintenance of menu tree relationships. It's much easier to alter relationships in a mySQL table than it is to open up a JavaScript file and edit the information in it; a non-technical person can easily accomplish the former, but may have difficulty with the latter. Consequently, a thorough cost-benefit analysis should be performed before making a decision as to which option is best suited to a specific case.