[PHP/HTML]Including a navbar with "active" element

Associate
Joined
21 May 2003
Posts
1,365
I don't know if this will be of any use to anyone, but I wrote it a while back and it's been handy on a few different projects. There are most likely better written examples on the net, but I thought i'd share it anyways.

Normally if you are highlighting the "active" navigation link for the current page (e.g. http://www.alistapart.com/articles/), you can't have the navigation menu as a seperate include because it needs to be slightly different for each page. (Having it as an include is handy because it means that you only need to edit one file should the navigation need updating).

Basically the code below allows you to have only one navigation list which you can include (using php) in your pages, whilst still retaining the "active" functionality.

Code:
<?php
	// set up the default navigation
	$nav1 = '<li><a href="addEnquiry.php">Add Enquiry</a></li>';
	$nav2 = '<li><a href="viewEnquiries.php">View/Edit Enquiries</a></li>';
	$nav3 = '<li><a href="createReport.php">Create Report</a></li>';
	$nav4 = '<li><a href="todaysCallbacks.php">Today\'s Callbacks</a></li>';
	
	// markup the correct list item as active - $thisPage is provided by the page which is including this file
	switch ($thisPage)
	{
		case 'ELTS :: Add Phone Enquiry':
			$nav1 = '<li><a href="#" id="current">Add Enquiry</a></li>';
		break;
		
		case 'ELTS :: View/Edit Phone Enquiries':
			$nav2 = '<li><a href="#" id="current">View/Edit Enquiries</a></li>';
		break;
				
		case 'ELTS :: Create Report':
			$nav3 = '<li><a href="#" id="current">Create Report</a></li>';
		break;
		
		case 'ELTS :: Today\'s Callbacks':
			$nav4 = '<li><a href="#" id="current">Today\'s Callbacks</a></li>';
		break;
	}

	// draw out the modified navbar with correct section active
	echo '<ul id="ELTSNav">';
		echo $nav1;
		echo $nav2;
		echo $nav3;
		echo $nav4;
	echo '</ul>';
	
?>

And then in each page you need to include the menu:

Code:
<?php
	// the name of the current page
	$thisPage = "ELTS :: Add Phone Enquiry";
	require_once('navBar.php');
?>

Feel free to point out any flaws or improvements.
 
Yeah, lazy as I am I did that for my last site as well, though I stored the navigation in an array with path name, and the script just loops through the array to print out the links, while checking $SERVER['PHP_SELF'] to decide whether it's "current" or not.
 
Code:
<?php

$nav = array(
    'Home' => '/',
    'About' => '/about',
    'Foo' => '/foo'
);

foreach($nav as $title => $link) {

    $current = ($link == substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?')) ? 'id="current"' : '';

    echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a>';

}

is my preferred method :)
 
robmiller said:
Code:
<?php

$nav = array(
    'Home' => '/',
    'About' => '/about',
    'Foo' => '/foo'
);

foreach($nav as $title => $link) {

    $current = ($link == substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?')) ? 'id="current"' : '';

    echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a>';

}

is my preferred method :)


Hehe, same as my method except for the $_SERVER['REQUEST_URI'] vs $_SERVER['PHP_SELF'] and id="current" vs class="current" (in case of multiple navigations on same page) that's pretty identical to what I do :D
 
robmiller said:
Well PHP_SELF just returns the name of the file, so if you're rewriting URIs or the script is in a subdirectory it won't match :)

PHP_SELF returns path and filename of script relative to root, so it returns the same value as request_uri in most cases. I'm clueless about apache url rewrite stuff but I do wonder if REQUEST_URI would be affected by it.

Also I can't use REQUEST_URI on IIS by default (haven't setup apache on local machine yet). Friend's wiki also suffer the same problem (his webhost was IIS) when request_uri was undefined. Seems you have to do extra stuff to fix that problem with IIS to resolve that problem, whilst PHP_SELF worked immediately.

Any ideas about the differences? The php manual didn't really offer much light.
 
robmiller said:
Code:
<?php

$nav = array(
    'Home' => '/',
    'About' => '/about',
    'Foo' => '/foo'
);

foreach($nav as $title => $link) {

    $current = ($link == substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?')) ? 'id="current"' : '';

    echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a>';

}

is my preferred method :)

The above method only works if the page is requested with a GET method, i.e. there's a question mark in the url.

This adaption should work with any url:
Code:
$nav = array(
    		'Add Record' => 'addRecord.php',
    		'Search Records' => 'searchRecords.php'
		);

foreach($nav as $title => $link) 
{

	$current = ($link == substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/')+1, strlen($link))) ? ' id="current"' : '';

	echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a></li>' . "\n";

}
 
LazyManc said:
The above method only works if the page is requested with a GET method, i.e. there's a question mark in the url.

  1. It works regardless of whether there's a query string, it just removes the query string if there is one.
  2. Almost all pages are fetched via GET, whether they have a query string or not. Examine an HTTP request sometime; telnet to google.com:80 and type:

    Code:
    GET / HTTP/1.1
    Host: google.com

    See? No question mark, GET method. 99.9% of the time you request a page, static or dynamic, question mark or no question mark, it's via GET.
 
Ok, I get what you're saying, but from my understanding:

Code:
strrpos($_SERVER['REQUEST_URI'], '?')
gives the number of characters upto the first "?"

so
Code:
substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?'))
gives the whole request string up until the first "?"

e.g. /news/20050401/article103.php or whatever.

so if you're comparing that against $link, then it's never going to match unless you put the full directory path in the array?

I may just not understand your directory structure.


Is there a less convoluted way of getting just say "addRecord.php" than using:
Code:
substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/')+1, strlen($link)))
bearing in mind that the file that calls the page may be an include?
 
It finds the last ? in the URL, note strrpos, not strpos. I've not tested it, but it should just return false should there not be a ? in the URL, and the substr should return the whole string. If PHP does something stupid like interpreting FALSE as 0, you can just cheat and do

Code:
if(!empty($_SERVER['QUERY_STRING'])) {
    $_SERVER['REQUEST_URI'] = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
}

It's easier if you're not using any kind of rewrites - you can just use $_SERVER['PHP_SELF'] - but I virtually always am, so there's no point :)
 
Back
Top Bottom