Header and footer navigation menus often require different markup structures — the header might use a multi-level dropdown while the footer renders a flat inline list. If you are already using a custom Walker_Nav_Menu, passing the menu location as a constructor argument lets you branch the output inside a single Walker class.
Problem: A theme registers the same navigation menu in both the header and footer, but each location needs different HTML structure or CSS classes — horizontal links in the header, a stacked list in the footer.
Solution: Create two Walker_Nav_Menu subclasses that output the desired markup, then pass each as the walker argument in the respective wp_nav_menu() call for the header and footer locations.
Step 1. Register both menu locations in functions.php:
<?php
register_nav_menus( [
'primary' => __( 'Primary Navigation', 'theme-name' ),
'secondary' => __( 'Footer Navigation', 'theme-name' ),
] );
Step 2. When calling wp_nav_menu(), instantiate the Walker with the location string as a constructor argument:
<?php
// In header.php
if ( has_nav_menu( 'primary' ) ) {
wp_nav_menu( [
'container' => false,
'theme_location' => 'primary',
'menu_id' => 'nav',
'menu_class' => 'nav navbar-nav',
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
'walker' => new Custom_Walker_Nav_Menu( 'primary' ),
] );
}
Step 3. In your Walker class, accept the location in the constructor and use it inside start_el() to vary the output:
<?php
class Custom_Walker_Nav_Menu extends Walker_Nav_Menu {
public $menu_location = 'primary';
public function __construct( $menu_location = 'primary' ) {
$this->menu_location = $menu_location;
}
public function start_el( &$output, $item, $depth = 0, $args = [], $id = 0 ) {
// Way 1: get the full menu object for the current location
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $locations[ $this->menu_location ] );
// Way 2: use the location string directly
$location = $this->menu_location;
if ( $location === 'primary' ) {
// Render header-specific markup
} else {
// Render footer-specific markup
}
}
}
This pattern keeps your Walker DRY — one class handles all locations — while still allowing completely different markup per location.
NOTE: If the markup difference between locations is significant, consider two separate Walker classes instead of branching inside one. A single large class with many conditionals can become hard to maintain as the theme grows.