2026年6月17日
2026年6月17日
WordPressのナビゲーションメニューをカスタマイズする方法・Walker・動的メニュー
はじめに
「ナビゲーションにアイコンやバッジを追加したい」「ログイン状態でメニューを変えたい」——WordPressのナビゲーションメニューはWalkerクラスをカスタマイズすることで高度な表示制御が可能です。
症状・原因
デフォルトのwp_nav_menu()はシンプルなHTMLを出力しますが、BootstrapのドロップダウンやメガメニューなどフレームワークのHTML構造に合わせるには、Walker_Nav_Menuクラスを拡張する必要があります。
解決手順
ステップ1:メニュー位置を登録する
// テーマのfunctions.phpにメニュー位置を登録
add_action( 'init', function() {
register_nav_menus( [
'primary' => 'グローバルナビゲーション',
'footer' => 'フッターメニュー',
'mobile' => 'モバイルメニュー',
'social' => 'ソーシャルメニュー',
] );
} );
管理画面でのメニュー割り当て:
外観 → メニュー → メニューを編集
→ 「メニューの設定」セクション
→ テーマの位置: 「グローバルナビゲーション」にチェック
→ 「メニューを保存」
ステップ2:wp_nav_menu()でメニューを表示する
// 基本的なメニュー表示
wp_nav_menu( [
'theme_location' => 'primary',
'menu_class' => 'nav-menu',
'container' => 'nav',
'container_class' => 'main-navigation',
'depth' => 2, // 2階層まで表示
'fallback_cb' => false, // メニュー未設定時に何も表示しない
] );
// メニューにBootstrapクラスを追加
wp_nav_menu( [
'theme_location' => 'primary',
'menu_class' => 'navbar-nav',
'container' => false,
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
] );
ステップ3:WalkerクラスでカスタムHTML構造を生成する
// BootstrapドロップダウンHTML構造に対応したWalker
class Bootstrap_Nav_Walker extends Walker_Nav_Menu {
public function start_lvl( &$output, $depth = 0, $args = null ) {
$output .= '<ul class="dropdown-menu">';
}
public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
$classes = empty( $item->classes ) ? [] : (array) $item->classes;
$has_children = in_array( 'menu-item-has-children', $classes );
$class_names = 'nav-item';
if ( $has_children ) $class_names .= ' dropdown';
if ( in_array( 'current-menu-item', $classes ) ) $class_names .= ' active';
$output .= '<li class="' . esc_attr( $class_names ) . '">';
$link_class = 'nav-link';
if ( $has_children ) $link_class .= ' dropdown-toggle';
$output .= '<a href="' . esc_url( $item->url ) . '"'
. ' class="' . $link_class . '"'
. ( $has_children ? ' data-bs-toggle="dropdown"' : '' )
. '>' . esc_html( $item->title ) . '</a>';
}
}
// 使い方
wp_nav_menu( [
'theme_location' => 'primary',
'walker' => new Bootstrap_Nav_Walker(),
] );
ステップ4:ログイン状態でメニューを動的に変更する
// ログイン状態に応じてメニューアイテムを追加
add_filter( 'wp_nav_menu_items', function( $items, $args ) {
if ( $args->theme_location !== 'primary' ) return $items;
if ( is_user_logged_in() ) {
$items .= '<li class="menu-item"><a href="' . get_dashboard_url() . '">ダッシュボード</a></li>';
$items .= '<li class="menu-item"><a href="' . wp_logout_url( home_url() ) . '">ログアウト</a></li>';
} else {
$items .= '<li class="menu-item"><a href="' . wp_login_url( get_permalink() ) . '">ログイン</a></li>';
}
return $items;
}, 10, 2 );
ステップ5:メニューアイテムにカスタムフィールドを追加する
// メニューアイテムの編集画面にアイコンフィールドを追加
add_action( 'wp_nav_menu_item_custom_fields', function( $item_id, $item ) {
$icon = get_post_meta( $item_id, '_menu_item_icon', true );
wp_nonce_field( 'menu_item_icon_nonce', 'menu_item_icon_nonce' );
echo '<p class="field-icon">';
echo '<label>アイコン(Font Awesome例: fa-home)</label>';
echo '<input type="text" name="menu-item-icon[' . $item_id . ']"'
. ' value="' . esc_attr( $icon ) . '">';
echo '</p>';
}, 10, 2 );
// 保存処理
add_action( 'wp_update_nav_menu_item', function( $menu_id, $menu_item_db_id ) {
if ( ! isset( $_POST['menu_item_icon'][ $menu_item_db_id ] ) ) return;
if ( ! wp_verify_nonce( $_POST['menu_item_icon_nonce'], 'menu_item_icon_nonce' ) ) return;
update_post_meta(
$menu_item_db_id,
'_menu_item_icon',
sanitize_text_field( $_POST['menu_item_icon'][ $menu_item_db_id ] )
);
}, 10, 2 );
// Walker内でアイコンを表示
// $icon = get_post_meta( $item->ID, '_menu_item_icon', true );
// if ( $icon ) $output .= '<i class="fas ' . esc_attr( $icon ) . '"></i> ';
注意事項
Walker_Nav_Menuを拡張する場合、WordPressのバージョンアップでWalkerクラスのメソッドシグネチャが変わることがあります。$argsパラメータのデフォルト値(= null)を設定しておくと互換性が保たれます。- メガメニューのような複雑なHTML構造は、Walkerクラスではなく
wp_nav_menu_itemsフィルターや専用のメガメニュープラグイン(Max Mega Menu等)を使う方が保守性が高い場合があります。 register_nav_menus()はafter_setup_themeアクションで呼び出すのが正しい方法です。initフックでも動作しますが、テーマの初期化タイミングに合わせるためafter_setup_themeが推奨です。
まとめ
ナビゲーションメニューのカスタマイズは「メニュー位置登録→wp_nav_menu()表示→Walkerクラス拡張→動的メニュー変更→カスタムフィールド追加」の順で実装できます。Bootstrap等のCSSフレームワークとの統合にはWalkerクラスが強力です。関連記事:WordPressでウィジェットをカスタマイズする方法、WordPressのfunctions.phpを安全に編集する方法。