Professional Documents
Culture Documents
By Team Melonfire
This article copyright Melonfire 20002002. All rights reserved.
Table of Contents
The Horns Of A Dilemma..................................................................................................................................1 Back To Class......................................................................................................................................................2 What's On The Menu?.......................................................................................................................................4 Children And Their Parents..............................................................................................................................5 I Say Method, You Say Madness.......................................................................................................................7 Playing With Nodes ...........................................................................................................................................10 Rounding Up The Family.................................................................................................................................13 Saving My Bookmarks.....................................................................................................................................17 Reaching Higher ................................................................................................................................................21 Collapsing Inwards...........................................................................................................................................27 Extending Yourself...........................................................................................................................................30
Back To Class
Before we begin, let's just go over the basics quickly: In PHP, a "class" is simply a set of program statements which perform a specific task. A typical class definition contains both variables and functions, and serves as the template from which to spawn specific instances of that class. Once a class has been defined, PHP allows you to spawn as many instances of the class as you like. These instances of a class are referred to as "objects". Each of these instances is a completely independent object, with its own properties and methods, and can thus be manipulated independently of other objects. This comes in handy in situations where you need to spawn more than one instance of an object for example, two simultaneous database links for two simultaneous queries, or two shopping carts. Classes also help you to separate your code into independent modules, and thereby simplify code maintenance and changes. A class definition typically looks like this:
<? class ShoppingCart { // this is where the properties are defined var $items; var $quantities; var $prices; ... // this is where the methods are defined function validate_credit_card() { // code goes here } ... } ?>
Once the class has been defined, an object can be spawned with the "new" keyword and assigned to a PHP variable,
Back To Class
?>
which can then be used to access all object methods and properties.
<? // accessing properties $myCart>items = array("eye of newt", "tail of lizard", "wings of bat"); $myCart>quantities = array(9, 4, 14); // accessing methods $myCart>validate_credit_card(); ?>
Back To Class
# # Table structure for table 'menu' # DROP TABLE IF EXISTS menu; CREATE TABLE menu ( id tinyint(3) unsigned NOT NULL auto_increment, label varchar(255) NOT NULL, link varchar(255), parent tinyint(3) unsigned DEFAULT '0' NOT NULL, PRIMARY KEY (id) ); # # # # # #
id unique identifier for each node label descriptive text for each node link URL for each node parent id of this node's parent
This design makes it easy to represent a hierarchical menu tree in terms of database records. For example, I could represent the following visual tree
USA | | | | | | | |
United Kingdom
mysql> SELECT * FROM menu; +++++ | id | link | label | parent | +++++ | 1 | | USA | 0 | | 2 | | California | 1 | | 3 | | Los Angeles | 2 | | 4 | | Massachusetts | 1 | | 5 | | Boston | 4 | | 6 | | United Kingdom | 0 | | 7 | | London | 6 | +++++ 7 rows in set (0.00 sec)
<? // menu.class.php // methods to obtain node and tree relationships class Menu {
} ?><hr noshade size=1 color=#cccccc></pre></blockquote> Now, since this class will be talking to a database, I need to add a few variables to hold databasespecific information. <blockquote><pre><hr noshade size=1 color=#cccccc><? class Menu { // set up some variables with default values // to hold database parameters // hostname, user and password
Building an Extensible Menu Class var $hostname; var $user; var $pass; // database and table containing menu data var $db; var $table; } ?>
PHP makes it possible to automatically execute a specific function when a new instance of a class is spawned. This function is referred to as a "constructor" and must have the same name as the class. In this case, I plan to initialize my Menu object with certain default values for the various database parameters. I have the option of assigning these variablevalue pairs individually, or writing a method to assign them all in one fell swoop; I pick the latter.
<? class Menu { // set up some variables // snip // constructor function Menu() { $this>set_database_parameters("localhost", "me", "bs49h5634", "apps", "menu"); }
// function: set database parameters // returns: none function set_database_parameters($hostname, $user, $password, $db, $table) { $this>hostname = $hostname; $this>user = $user; $this>password = $password; $this>db = $db; $this>table = $table; } }
In case you're wondering, the $this prefix provides a convenient way to access variables and functions which are "local" to the class Now, all the methods listed above will be querying the database for information. Since the connectandquery code is common to all of them, I can extract it into a separate method named query().
<? class Menu { // other methods // function: execute query $query // returns: result identifier function query($query) { // connect $connection = mysql_connect($this>hostname, $this>user, $this>pass) or die ("Cannot connect to database"); // run query $ret = mysql_db_query($this>db, $query, $connection) or die ("Error in query: $query"); // return result identifier return $ret; } } ?>
All my object methods can now simply use query() to execute SQL queries on the database. Further if I ever decide to move to another database, I need only update the code in this single function to ensure that my class will continue to work with the new system.
<? class Menu { // other methods // function: get parent // returns: node id function get_parent($id) { $query = "SELECT parent FROM $this>table WHERE id = '$id'"; $result = $this>query($query); $row = mysql_fetch_row($result); return $row[0]; } } ?>
An offshoot of this is the is_root_node() method, used to test whether a particular node is at the base of the menu tree.
<? class Menu { // other methods // function: is this node at the root of the tree? // returns: boolean function is_root_node($id) { if($this>get_parent($id) == 0) { return 1; } else { return 0; } }
10
The get_label() and get_link() methods accept a node id and return the corresponding text and URL from the table.
<? class Menu { // other methods // function: get label for $id // returns: string function get_label($id) { $query = "SELECT label FROM $this>table WHERE id = '$id'"; $result = $this>query($query); $row = mysql_fetch_row($result); return $row[0]; } // function: get link for $id // returns: string function get_link($id) { $query = "SELECT link FROM $this>table WHERE id = '$id'"; $result = $this>query($query); $row = mysql_fetch_row($result); return $row[0]; } } ?>
Using the menu table constructed a few pages ago, the code
would return
11
12
<? class Menu { // other methods // function: get next level of menu tree // returns: array function get_children($id) { $query = "SELECT id, label, link FROM $this>table WHERE parent = '$id'"; $result = $this>query($query); $count = 0; while ($row = mysql_fetch_array($result)) { $children[$count]["id"] = $row["id"]; $children[$count]["label"] = $row["label"]; $children[$count]["link"] = $row["link"]; $count++; } return $children; } } ?>
This method accepts a node id and queries the database for a list of items which reference that node in the "parent" column. These records are packaged as an array of arrays and returned to the calling function. Here's an example of how it could be used:
<? $obj = new Menu(); // get children $arr = $obj>get_children(1); echo "<ul>"; // iterate through array for ($x=0; $x<sizeof($arr); $x++) { echo "<li>" . $arr[$x]["label"];
13
California Massachusetts
A useful corollary of this is the get_type() method, which can be used to identify whether a particular node on the tree has children or not in other words, whether it is a leaf or a branch.
<? class Menu { // other methods // function: test whether this id is a branch or leaf // returns: boolean function get_type($id) { if($this>get_children($id) ) { return 1; } else { return 0; } } } ?>
The get_ancestors() method does the reverse of the get_children() method it returns a list of nodes between the tree root and the supplied node identifier, starting from the top of the menu tree and proceeding downwards.
14
Building an Extensible Menu Class <? class Menu { // other methods // function: return a list of this node's parents // by travelling upwards all the way to the root of the tree // returns: array function get_ancestors($id, $count = 0) { // get parent of this node $parent = $this>get_parent($id); // if not at the root, add to $ancestors[] array if($parent) { $this>ancestors[$count]["id"] = $parent; $this>ancestors[$count]["label"] = $this>get_label($parent); $this>ancestors[$count]["link"] = $this>get_link($parent); // recurse to get the parent of this parent $this>get_ancestors($this>ancestors[$count]["id"], $count+1); // all done? at this stage the array contains a list in bottomup order // reverse the array and return return array_reverse($this>ancestors); } } } ?>
Returning to the example above, an attempt to find out the ancestors of node id 5 (Boston)
<? $obj = new Menu(); // get children $arr = $obj>get_ancestors(5); echo "<ul>"; // iterate through array for ($x=0; $x<sizeof($arr); $x++) { echo "<li>" . $arr[$x]["label"]; } echo "</ul>"; ?>
15
USA Massachusetts
Finally, the print_menu_tree() method comes in handy while debugging, if you need to visually see the complete menu tree with its internal dependencies.
<? class Menu { // other methods // function: display complete menu tree (useful when debugging) // returns: HTML list function print_menu_tree($id = 0) { $result = $this>get_children($id); echo "<ul>"; for ($x=0; $x<sizeof($result); $x++) { echo "<li>" . $result[$x]["label"] . "[" . $result[$x]["id"] . "]"; $this>print_menu_tree($result[$x]["id"]); } echo "</ul>"; } } ?>
16
Saving My Bookmarks
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.zip Since 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 subcategories 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:
Saving My Bookmarks
17
Building an Extensible Menu Class // 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);
Saving My Bookmarks
18
Building an Extensible Menu Class 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"] . ">" .
Saving My Bookmarks
19
Building an Extensible Menu Class $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:
Saving My Bookmarks
20
Reaching Higher
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 JavaScriptbased 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 nittygritty of how it works there's some excellent documentation if you're interested but rather plan to focus on how this clientside 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:
mysql> SELECT id, label, parent FROM menu; ++++ | id | label | parent | ++++ | 1 | Services | 0 | | 2 | Company | 0 | | 3 | Media Center | 0 | | 4 | Your Account | 0 | | 5 | Community | 0 | | 6 | For Content Publishers | 1 | | 7 | For Small Businesses | 1 | | 8 | Background | 2 | | 9 | Clients | 2 | | 10 | Addresses | 2 | | 11 | Jobs | 2 | | 12 | News | 2 | | 13 | Press Releases | 3 | | 14 | Media Kit | 3 | | 15 | Log In | 4 | | 16 | Columns | 5 | | 17 | Colophon | 16 | | 18 | Cut | 16 | | 19 | Boombox | 16 | | 20 | The HITG Report | 16 | | 21 | Trog | 16 | ++++ 21 rows in set (0.06 sec)
If I was to build this menu using the HIERmenus system, I would need to manually code a series of JavaScript arrays, like this:
Reaching Higher
21
Building an Extensible Menu Class HM_Array1 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Services", "http://www.melonfire.com/services/", 1, 0, 1], ["Company", "http://www.melonfire.com/company/", 1, 0, 1], ["Media Center", "http://www.melonfire.com/mcenter/", 1, 0, 1], ["Your Account", "http://www.melonfire.com/account/", 1, 0, 1], ["Community", "http://www.melonfire.com/community/", 1, 0, 1] ]; HM_Array1_1 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["For Content Publishers", "http://www.melonfire.com/services/content.html", 1, 0, 0], ["For Small Businesses", "http://www.melonfire.com/services/sbs.html", 1, 0, 0] ]; HM_Array1_2 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Background", "http://www.melonfire.com/company/background.html", 1, 0, 0], ["Clients", "http://www.melonfire.com/company/clients.html", 1, 0, 0], ["Addresses", "http://www.melonfire.com/company/addresses.html", 1, 0, 0], ["Jobs", "http://www.melonfire.com/company/jobs.html", 1, 0, 0], ["News", "http://www.melonfire.com/company/news.php3", 1, 0, 0] ]; HM_Array1_3 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Press Releases", "http://www.melonfire.com/mcenter/pr.html", 1, 0, 0], ["Media Kit", "http://www.melonfire.com/mcenter/mkit.html", 1, 0, 0] ]; HM_Array1_4 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Log In", "http://www.melonfire.com/account/index.html", 1, 0, 0] ]; HM_Array1_5 = [ [180, 200, 50, "black", "white", "white", "black", "black",
Reaching Higher
22
Building an Extensible Menu Class "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Columns", "http://www.melonfire.com/community/columns/", 1, 0, 1] ]; HM_Array1_5_1 = [ [180, 200, 50, "black", "white", "white", "black", "black", "gray", 0, 0, 0, 1, 1, 1, "null", "null", ,], ["Colophon", "http://www.melonfire.com/community/columns/colophon/", 1, 0, 0], ["Cut", "http://www.melonfire.com/community/columns/cut/", 1, 0, 0], ["Boombox", "http://www.melonfire.com/community/columns/boombox/", 1, 0, 0], ["The HITG Report", "http://www.melonfire.com/community/columns/thr/", 1, 0, 0], ["Trog", "http://www.melonfire.com/community/columns/trog/", 1, 0, 0] ];
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 userfriendly 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.
if(HM_IsMenu) { document.write("<SCR" + SRC='HM_Arrays.js.php ' "IPT>"); document.write("<SCR" + SRC='HM_Script"+ HM_BrowserString +".js' "IPT>"); }
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\",
Reaching Higher
23
Building an Extensible Menu Class \"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);
Reaching Higher
24
Building an Extensible Menu Class 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>
Reaching Higher
25
Building an Extensible Menu Class <script language="JavaScript1.2" src="HM_Loader.js" type='text/javascript'></script> </body> </html>
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 clientside application and successfully connected it to a serverside 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 nontechnical person can easily accomplish the former, but may have difficulty with the latter. Consequently, a thorough costbenefit analysis should be performed before making a decision as to which option is best suited to a specific case.
Reaching Higher
26
Collapsing Inwards
If you go back a few pages, you'll notice that one of the design goals of this Menu object was to separate the visual presentation of a menu from the relationships between the various nodes. I've already demonstrated how the same Menu object can be used to create a directory and a hierarchical menu tree with standard methods. My third example is similar to the second, again connecting a JavaScriptbased menu system to the menu database to dynamically build a menu tree. For this, I plan to use another very popular menu constructor, FolderTree (free version available at http://www.geocities.com/marcelino_martins/foldertree.html ), which uses Windows Explorerstyle files and folders to display a hierarchy of items. First, I need an HTML page to invoke FolderTree and display the menu:
<html> <head> <basefont face="Arial"> <link rel="stylesheet" href="ftie4style.css"> <! Infrastructure code for the tree > <script src="ftiens4.js"></script> <! Execution of the code that actually builds the specific tree > <script src="menu.js.php"></script> <script> initializeDocument() </script> </head> <body bgcolor=white> </body> </html>
As you can see, this file sources "menu.js.php", which contains the actual menu data. This file is usually created manually as per the user's requirements; I plan to hook it up to my database table to generate it dynamically. Here's the code:
Collapsing Inwards
27
Building an Extensible Menu Class foldersTree = gFld("Melonfire", "http://www.melonfire.com"); <? // initialize object include("menu.class.php"); $obj = new Menu(); // counter used to create tree nodes $count = 0; function buildMenu($id, $node) { global $obj; global $count; // get children $children = $obj>get_children($id); for ($x=0; $x<sizeof($children); $x++) { // write the name of this node $newNode = "aux" . $count; // if folder if($obj>get_type($children[$x]["id"]) == 1) { // call appropriate FolderTree function to display folder icon $count++; $str = $newNode . " = insFld(" . $node . ", gFld(\"" . $children[$x]['label'] . "\", \"" . $children[$x]['link'] . "\"));"; print $str; // and recurse for next level buildMenu($children[$x]["id"], $newNode); } else { // if last level // call appropriate FolderTree function to display file icon $str = "insDoc(" . $node . ", gLnk(2, \"" . $children[$x]['label'] . "\", \"" . $children[$x]['link'] . "\"));"; print $str; } } } // initiate recursive function buildMenu(0, "foldersTree"); ?>
Collapsing Inwards
28
You just gotta love those recursive functions! Here's what it all looks like:
Collapsing Inwards
29
Extending Yourself
All the examples you've seen thus far have used the same standard API defined within the Menu object. However, this assumes one important thing that a database table (in the format described) has already been created and populated with menu records. In case this is an unreasonable assumption for your specific requirements, you might consider adding a few method calls to add and delete nodes respectively.
<? class Menu { // other methods // function: add a record to the menu table function create_node($label, $link, $parent) { $this>query("INSERT INTO $this>table(label, link, parent) VALUES ('$label', '$link', '$parent')"); } // function: remove a record from the menu table function remove_node($id) { $this>query("DELETE FROM $this>table WHERE id = '$id'"); } } ?>
You might also want to consider developing a simple administration interface to these method calls, so that users can easily modify the menu tree via a GUI. And that's about all for the moment. In this article, you expanded your knowledge of PHP's OOP capabilities by actually using all that theory to build something useful a menu widget which can be used to describe the relationships within a hierarchical menu system, independent of how the menu is visually presented. If you work with menu systems, whether on a Web site, within a Web application or on an embedded system, you might find this object a handy tool in your next development effort. If you're a novice programmer struggling to understand how OOP can make your life easier, I hope this article offered some pointers, as well as some illustration of how objectoriented programming works. And if you don't fit into either of those categories well, I hope you found it interesting and informative, anyway. See you soon! Note: All examples in this article have been tested on Linux/i586 with PHP4, HIERmenus 4.0.12, and
Extending Yourself
30
Building an Extensible Menu Class FolderTree 2.0. HIERmenus and FolderTree copyright their respective authors. Examples are illustrative only, and are not meant for a production environment. YMMV!
Extending Yourself
31