Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To reuse the same navigation on multiple PHP pages, put the menu markup in a separate file and load it with require or include:
<?php
require __DIR__ . '/includes/menu.php';
?>
PHP includes and executes the file on the server, placing its output where the statement appears in the page. It does not call the file through the browser or create a redirect.
Build a reusable PHP menu
Start with this project structure:
my-site/
├── index.php
├── about.php
└── includes/
└── menu.php
Put only the reusable navigation fragment in includes/menu.php:
Recommended Free Tools
<nav aria-label="Primary navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about.php">About</a></li>
<li><a href="/contact.php">Contact</a></li>
</ul>
</nav>
The page containing the menu must be processed by PHP, so use a .php file and open it through a PHP-capable web server:
#1 Best Overall
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home</title>
</head>
<body>
<?php require __DIR__ . '/includes/menu.php'; ?>
<main>
<h1>Home</h1>
</main>
</body>
</html>
Everything outside PHP tags in menu.php is sent as HTML. The menu file normally should not contain <!doctype html>, <html>, <head>, or <body>; the page itself should own that document structure.
require versus include
For a site-wide menu, require is usually the appropriate choice when the page should not continue without its navigation. If the file is missing, PHP stops execution with an error. PHP documents require as otherwise equivalent to include: require and include.
| Statement | If the file is missing | Typical use |
|---|---|---|
include |
Warning; execution may continue | Optional fragment |
require |
Error; execution stops | Required layout or menu |
include_once |
Warning; includes at most once | Optional shared file |
require_once |
Error; requires at most once | Bootstrap, configuration, or library |
The _once variants prevent the same file from being included more than once during one script execution. They are useful for declarations and initialization code, but a menu rendered once does not automatically need require_once. If a layout and a page both render the menu, require_once does not necessarily prevent duplicate HTML output caused by separate rendering logic.
Free tools Windows power users keep installed
One-click scans. No signup required.
Use __DIR__ for reliable paths
This basic form works only when PHP can resolve the file using the current path rules:
<?php include 'menu.php'; ?>
A more predictable form anchors the path to the directory of the PHP file containing the statement:
Rank #2
<?php
require __DIR__ . '/includes/menu.php';
?>
__DIR__ avoids depending on the process working directory or the configured PHP include_path. It is particularly helpful when a page is moved, run from the command line, or served through a different entry point. See PHP’s documentation for include-path behavior.
Common directory layouts
If the menu is beside the page:
site/
├── index.php
└── menu.php
require __DIR__ . '/menu.php';
If it is in an includes directory:
require __DIR__ . '/includes/menu.php';
If the page is nested one directory below the project root:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →site/
├── includes/
│ └── menu.php
└── admin/
└── dashboard.php
// admin/dashboard.php
require __DIR__ . '/../includes/menu.php';
Here, .. moves from admin to its parent directory.
Highlight the current menu item
The clearest approach for a small site is to set an explicit page key before including the menu:
<?php
$currentPage = 'products';
require __DIR__ . '/includes/menu.php';
?>
Then use that value in menu.php:
<?php
$currentPage = $currentPage ?? '';
?>
<nav aria-label="Primary navigation">
<ul>
<li>
<a href="/"
class="<?= $currentPage === 'home' ? 'active' : '' ?>"
<?= $currentPage === 'home' ? 'aria-current="page"' : '' ?>>
Home
</a>
</li>
<li>
<a href="/products.php"
class="<?= $currentPage === 'products' ? 'active' : '' ?>"
<?= $currentPage === 'products' ? 'aria-current="page"' : '' ?>>
Products
</a>
</li>
</ul>
</nav>
Included files inherit variables available at the point of inclusion, which is why $currentPage is visible. An explicit key is more reliable than inspecting URLs when several public routes use one controller or URL rewriting. PHP documents this scope behavior in its include reference.
For simple sites, alternatives include $_SERVER['SCRIPT_NAME'] or a parsed $_SERVER['REQUEST_URI']. The former identifies the executed script, not always the public route; the latter represents the requested URI and may include a query string. Do not use either value as a file path. Avoid using PHP_SELF in output without proper handling because it can contain user-controlled path information: server variables.
Use a data-driven menu for larger navigation
Separating menu data from its HTML makes links easier to add and reorder:
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errors<?php
$currentPage = 'products';
$menuItems = [
'home' => ['label' => 'Home', 'url' => '/'],
'products' => ['label' => 'Products', 'url' => '/products.php'],
'contact' => ['label' => 'Contact', 'url' => '/contact.php'],
];
require __DIR__ . '/includes/menu.php';
In includes/menu.php:
<nav aria-label="Primary navigation">
<ul>
<?php foreach ($menuItems as $key => $item): ?>
<?php $isCurrent = $key === $currentPage; ?>
<li>
<a href="<?= htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8') ?>"
<?= $isCurrent ? 'aria-current="page"' : '' ?>>
<?= htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8') ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</nav>
Use htmlspecialchars() when dynamic labels or URLs are inserted into HTML text or attributes. Specify UTF-8 explicitly; this is HTML-context escaping, not complete URL validation or permission checking. See PHP’s htmlspecialchars documentation.
Do not confuse PHP paths with browser URLs
The path in require identifies a file on the server. The href values in the generated menu are resolved by the browser.
This relative link can break on a nested page:
<a href="about.php">About</a>
From /admin/dashboard.php, the browser may request /admin/about.php. If the public page is at the site root, use:
<a href="/about.php">About</a>
For an application installed under /my-site, centralize the base path:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #4
<?php
$basePath = '/my-site';
$url = $basePath . '/about.php';
?>
<a href="<?= htmlspecialchars($url, ENT_QUOTES, 'UTF-8') ?>">About</a>
A URL helper or framework router is preferable once deployment paths and routes become more complex.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Run and test the example
Do not double-click the PHP file and open it as a local document. From the project directory, use PHP’s built-in development server:
php -S localhost:8000
Then visit http://localhost:8000/. This server is intended for local development, not production hosting.
If PHP reports “Failed opening required,” temporarily inspect the resolved path:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minutePC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11<?php
$menuPath = __DIR__ . '/includes/menu.php';
var_dump($menuPath, is_file($menuPath), is_readable($menuPath));
require $menuPath;
?>
Check the directory level, filename capitalization, deployment copy, and file permissions. Remove debugging output afterward. You can also fail with a clearer message:
<?php
$menuPath = __DIR__ . '/includes/menu.php';
if (!is_file($menuPath)) {
throw new RuntimeException('Menu file not found: ' . $menuPath);
}
require $menuPath;
If PHP source appears in the browser, the server is not processing that file as PHP, the extension or server mapping is wrong, or the PHP tags are malformed.
Keep dynamic includes safe
Never allow request data to become an include path:
<?php
$page = $_GET['page'];
require __DIR__ . '/pages/' . $page . '.php';
Depending on validation and configuration, this can lead to local-file-inclusion or path-traversal vulnerabilities. Map user-facing keys to fixed server-side paths instead:
<?php
$pages = [
'home' => __DIR__ . '/pages/home.php',
'about' => __DIR__ . '/pages/about.php',
];
$key = $_GET['page'] ?? 'home';
if (!array_key_exists($key, $pages)) {
http_response_code(404);
exit('Page not found');
}
require $pages[$key];
For sensitive configuration and application code, keep view or include files outside the public document root where practical:
project/
├── public/
│ └── index.php
└── src/
└── views/
└── menu.php
// public/index.php
require dirname(__DIR__) . '/src/views/menu.php';
This reduces accidental direct exposure but is not a replacement for correct server configuration, permissions, and application security. PHP discusses this layout consideration in its include documentation.
When to use a template system
Native require is enough for a small PHP site. A framework layout, Twig, or a component-based view system becomes worthwhile when the application needs layout inheritance, automatic escaping, reusable components, explicit view-data contracts, or route names that are independent of physical filenames.
For one shared menu, adding a framework is unnecessary. Start with a partial and reliable path; introduce a view system when repeated templates and routing complexity justify it.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

