preloaded image preloaded image preloaded image

Lazy Menu System

You added how many pages? To which directories? Ugh!

If you're anything like me then you find it tedious and boring to update menus, particularly for minor changes. Now, sure, step 1 to any lazy menu system is to create a separate menu file and use PHP includes to plop it into each of your pages. We have been there and done that. Sure, this makes it so that we don't have to update the menu any more than one time in one page for a change. That's all well and good, but what if we don't want to update the menu AT ALL? Ever?

Well, now there's a way. This is the main bit of PHP coding that drives the automated menu system:

<?php $path = $_SERVER['DOCUMENT_ROOT']."/layouts/"; //this finds the directory "layouts" based on the root filepath $dir_handle = @opendir($path) or die("Unable to open $path"); //error handling, always a good idea while ($file = readdir($dir_handle)) { if($file!="." && $file!=".." && $file!="index.php" && !strpos($file, ".html")){ //this weeds out parent directory listings and any HTML files (a personal choice but recommended) $file_copy = $file; $file_page = $file; $file_page = str_replace(".php","",$file_page); //start dropping file extensions $file_page = str_replace(".html","",$file_page); $file_page = str_replace(".css","",$file_page); $file_copy = str_replace("_"," ",$file_copy); //turn underscores into spaces $file_copy = str_replace(".php","",$file_copy); $file_copy = str_replace(".html","",$file_copy); $file_copy = str_replace(".css","",$file_copy); $file_copy = str_replace("php","PHP",$file_copy); //convert instances of PHP, HTML, and CSS to all uppercase $file_copy = str_replace("html","HTML",$file_copy); $file_copy = str_replace("css","CSS",$file_copy); $file_copy = ucwords($file_copy); //convert remaining text to title case echo " <li><a href=\"/layouts/?page=$file_page\""; //output list item if(strlen($file_copy)>10 && strlen($file_copy)<=18){ //check length of text in <a> elements so our links don't wrap -- use of this depends on how your menu is constructed echo "style=\"width:11.5em;\""; //adjust width of <a> elements to compensate for longer text } else if(strlen($file_copy)>18 && strlen($file_copy)<=26){ echo "style=\"width:13em;\""; } else if(strlen($file_copy)>26 && strlen($file_copy)<=40){ echo "style=\"width:20em;\""; } echo ">$file_copy</a></li>\n"; //close our list item for this file and move on to next file, if applicable } } closedir($dir_handle); ?>

Now in order to use this we have to bear in mind that every single file in the listed directory (including subdirectories but not the files within those subdirectories) will be listed as submenu items. The only exceptions in the above code are that ".", "..", and any file with an extension of ".html" will be excluded. This means a couple of things. One: we have to name our files semantically with how they will be displayed in the menu. Underscores and completely lower-case text is OK because the script corrects for that, but any numbers, missing spaces, or other odd characters will fly straight into your menu. Two: we have to make sure that our directories do not contain files or subdirectories that should not be listed in a menu.

You can tweak the script to ignore files with specific words in them if you like, so a workaround for rule #2 above would be simply putting a blocking string of characters into the names of files/directories that should not be made into menu items. Something unlikely to come up in the naming convention of menu items would be best (such as using a prefix of "xxx" -- really anything will work as long as you are consistent and don't forget about the rule when you name files that you DO want to include in the menu).

Additionally, you can block all subdirectories from being listed in a category if you wish. All you have to do is add "&& !is_dir($file)" in the if statement. The result would look like this:

if($file!="." && $file!=".." && $file!="index.php" && !strpos($file, ".html") && !is_dir($file)){ $file_copy = $file; $file_page = $file; $file_page = str_replace(".php","",$file_page); ...etc... }

So now that you have figured out how you will name your files to make this work for you this is how you will build your "menu.php" (or name it whatever you like, really). This is literally how the menu for this site is generated:

<div id="header"><!--- Open Main Menu --> <div id="logo"></div> <ul id="main_menu"> <li><a href="/">Home</a></li> <!--there are no submenu items generated for the home page so we just list this one straight on its own...--> <li><a href="/menus/">Menus</a> <ul> <?php $path = $_SERVER['DOCUMENT_ROOT']."/menus/"; //this finds the directory "menus" based on the root filepath $dir_handle = @opendir($path) or die("Unable to open $path"); //error handling, always a good idea while ($file = readdir($dir_handle)) { if($file!="." && $file!=".." && $file!="index.php" && !strpos($file, ".html")){ //this weeds out parent directory listings and any HTML files (a personal choice but recommended) $file_copy = $file; $file_page = $file; $file_page = str_replace(".php","",$file_page); //start dropping file extensions $file_page = str_replace(".html","",$file_page); $file_page = str_replace(".css","",$file_page); $file_copy = str_replace("_"," ",$file_copy); //turn underscores into spaces $file_copy = str_replace(".php","",$file_copy); $file_copy = str_replace(".html","",$file_copy); $file_copy = str_replace(".css","",$file_copy); $file_copy = str_replace("php","PHP",$file_copy); //convert instances of PHP, HTML, and CSS to all uppercase $file_copy = str_replace("html","HTML",$file_copy); $file_copy = str_replace("css","CSS",$file_copy); $file_copy = ucwords($file_copy); //convert remaining text to title case echo " <li><a href=\"/menus/?page=$file_page\""; //output list item if(strlen($file_copy)>10 && strlen($file_copy)<=18){ //check length of text in <a> elements so our links don't wrap -- use of this depends on how your menu is constructed echo "style=\"width:11.5em;\""; //adjust width of <a> elements to compensate for longer text } else if(strlen($file_copy)>18 && strlen($file_copy)<=26){ echo "style=\"width:13em;\""; } else if(strlen($file_copy)>26 && strlen($file_copy)<=40){ echo "style=\"width:20em;\""; } echo ">$file_copy</a></li>\n"; //close our list item for this file and move on to next file, if applicable } } closedir($dir_handle); ?> <li><a href="/php/">PHP Functions</a> <ul> <?php $path = $_SERVER['DOCUMENT_ROOT']."/php/"; //this finds the directory "php" based on the root filepath $dir_handle = @opendir($path) or die("Unable to open $path"); //error handling, always a good idea while ($file = readdir($dir_handle)) { if($file!="." && $file!=".." && $file!="index.php" && !strpos($file, ".html")){ //this weeds out parent directory listings and any HTML files (a personal choice but recommended) $file_copy = $file; $file_page = $file; $file_page = str_replace(".php","",$file_page); //start dropping file extensions $file_page = str_replace(".html","",$file_page); $file_page = str_replace(".css","",$file_page); $file_copy = str_replace("_"," ",$file_copy); //turn underscores into spaces $file_copy = str_replace(".php","",$file_copy); $file_copy = str_replace(".html","",$file_copy); $file_copy = str_replace(".css","",$file_copy); $file_copy = str_replace("php","PHP",$file_copy); //convert instances of PHP, HTML, and CSS to all uppercase $file_copy = str_replace("html","HTML",$file_copy); $file_copy = str_replace("css","CSS",$file_copy); $file_copy = ucwords($file_copy); //convert remaining text to title case echo " <li><a href=\"/php/?page=$file_page\""; //output list item if(strlen($file_copy)>10 && strlen($file_copy)<=18){ //check length of text in <a> elements so our links don't wrap -- use of this depends on how your menu is constructed echo "style=\"width:11.5em;\""; //adjust width of <a> elements to compensate for longer text } else if(strlen($file_copy)>18 && strlen($file_copy)<=26){ echo "style=\"width:13em;\""; } else if(strlen($file_copy)>26 && strlen($file_copy)<=40){ echo "style=\"width:20em;\""; } echo ">$file_copy</a></li>\n"; //close our list item for this file and move on to next file, if applicable } } closedir($dir_handle); ?> <!--...[And so on]...--> </ul> </div><!-- Close Main Menu -->

That's it! Just load up as many of these modules as you need and with each one specify the next folder to be archived as a menu. The link structure may change based on how you have your PHP navigation set up. For me, all files are routed through index.php in each directory where they are handled for errors and if a valid page is given (?page=xxx) then the associated file is served. If you have things set up differently be aware that the href's in my code will need to be adjusted to work for you.