A Tree (Sliding) Menu Written In PHP

Recently posed on Yahoo! Answers:

Regarding PHP, what would be a good way to make dynamic tree like menu?

So when the user first looks at the page, they see
2004
2005
2006
2007

When they click on the year, a sub menu drops down as follows.

2004
2005
–january
–february
–march
–…..
–december
2006
2007
etc.
if they click on the year again, the menu will collapse
im trying to avoid javascript at all possible

thanks

For the most part, tree (aka sliding, aka dynamic) menus these days seldom involve posting back to the server; they’re more commonly made either with CSS alone, JavaScript alone or a combination of the two. However, some folks want to keep things both aesthetic and primitive, for maximum compatibility.

So, without further ado, here’s a tree (slider / dynamic) menu written solely in PHP.

Our script will do the following:

  • Receive from the querystring the current year selected and test it for type and range (that is, make sure it’s an integer between a starting and ending year). If there is not a year in the querystring, all the years will be collapsed.
  • Display the months for the selected year, with a link back to the same page that adds month and year variables to the querystring.
  • We’ll pretty it all up by using nested lists and styling them with CSS.

OK, Step 1 is to set some variables. We’re going to use a loop to output the years for this menu, so we need to know the lowest and highest years we’ll be outputting. Setting these as virtual constants makes it easier to amend our code for later dates.

We next set the value of a variable we’ll call $theyear to be the same as the y value in our querystring. Finally, we test to see if the y variable is present, in the proper format and in range; if any of those are not the case, we set the value of $theyear to be zero, for reasons that will be explained shortly.

$MIN_YEAR = 2004;
$MAX_YEAR = 2007;
$theyear = $_GET['y'];

if(ereg('^[0-9]{4}$', $theyear)) {
	if($theyear > $MAX_YEAR || $theyear < $MIN_YEAR) {
		$theyear = 0;
	}
}
else {
	$theyear = 0;
}

Before we get into the code that will actually output our menu, we need to create two functions.

The first we will call monthName. It will take an integer as an argument and return a string with the name of the month that corresponds to the integer. For example, if it gets 1 as an argument, it will return “January,” if it gets 12 as an argument, it will return “December.” If the input is out of range, the function will return “No Month.”

function monthName($intput) {
	switch($intput) {
		case 1:
			$out = "January";
			break;
		case 2:
			$out = "February";
			break;
		case 3:
			$out = "March";
			break;
		case 4:
			$out = "April";
			break;
		case 5:
			$out = "May";
			break;
		case 6:
			$out = "June";
			break;
		case 7:
			$out = "July";
			break;
		case 8:
			$out = "August";
			break;
		case 9:
			$out = "September";
			break;
		case 10:
			$out = "October";
			break;
		case 11:
			$out = "November";
			break;
		case 12:
			$out = "December";
			break;
		default:
			$out = "No Month";
	}
	return $out;
}


The second function we need will be called makeURL. The issue we face in using this script is that we'll be dynamically creating navigation links based on the year selected. We could normally handle that by just appending the appropriate y and m (year and month) variables to the current script's name.

But what if we have other querystring variables? We need to preserve those so we can pass them back to the page, along with the newly selected month and year variables. So, to accommodate that, we get from PHP the name of the current script, examine each querystring variable, and if it isn't a year or month variable, we append it right back on to the querystring.

We replace the year value for the querystring with the new year generated by the menu; and, if we provide an optional $month parameter to the function, we append that month to the URL as well.


function makeUrl($year, $month = 0) {
	$url = $_SERVER['PHP_SELF'] . "?";

	foreach($_GET as $key => $value) {
		if($key != 'y' && $key != 'm') {
			$url .= "$key=$value&amp;";
		}
	}

	$url .= "y=$year";

	if($month != 0) {
		$url .= "&amp;m=$month";
	}
	return $url;
}

The code to output the tree / sliding menu itself is very simple. We just create an unordered list and start iterating through all the years from the $MIN_YEAR to the $MAX_YEAR, writing each out as a list item.

If the year we are outputting matches the year in the querystring, we create another unordered list beneath the current list item, and output all 12 months of the year. We create new nav links as we go along.

To finish up, we close our loops, and that’s it.

echo "<ul>\n";
for($i = $MIN_YEAR; $i <= $MAX_YEAR; $i++) {
	echo "<li lang=\"majorBranch\"><a href=\"" . makeUrl($i) . "\">$i";
	if($theyear == $i) {
		echo "</a>";
		echo "<ul>\t";
		for($x = 1; $x <= 12; $x++) {
			echo "<li lang=\"minorBranch\"><a href=\"" . makeUrl($i, $x) ."\">".monthName($x)."</a></li>\n";
		}
		echo "</ul>\n";
	}
	else {
		echo "</a>";
	}
	echo "</li>\n";
}
echo "</ul>\n";

You can see a working demo of this at http://demo.dougv.com/phptreemenu/. And, of course, you can download the source code: A Tree (Sliding) Menu Written In PHP Demo Code

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!