結論
クラシックテーマにメニューを追加するには、次の3か所を作ります。
functions.phpのafter_setup_themeでregister_nav_menus()を呼び、メニュー位置を登録する- テンプレートに
wp_nav_menu( array( 'theme_location' => '位置名' ) )を書く - 管理画面の「外観 > メニュー」で、メニューを作り、位置に割り当てる
「メニューが出ない」「固定ページの一覧が出てしまう」原因の多くは、位置にメニューが未割り当てであることです。fallback_cb を false にすると、未割り当て時は何も出力しなくなります。
原因・仕組み
register_nav_menus() は「位置」の名前を登録するだけで、メニュー自体は作りません。wp_nav_menu() は、theme_location に割り当てられたメニューを探し、なければ fallback_cb(既定は wp_page_menu)を呼びます。公式リファレンスによると、メニュー指定→位置の割り当て→最初の空でないメニュー→fallback_cb の順に探し、見つからず fallback_cb もなければ false を返します。
そのため、割り当てを忘れても、エラーではなく「固定ページの一覧」がフォールバックとして表示されます。
手順(サンプルコード)
1. メニュー位置を登録する
add_action( 'after_setup_theme', function () {
register_nav_menus( array(
'primary' => 'メイン',
'footer' => 'フッター',
) );
} );
2. テンプレートで表示する
<?php if ( has_nav_menu( 'primary' ) ) : ?>
<?php
wp_nav_menu( array(
'theme_location' => 'primary',
'container' => 'nav',
'container_class' => 'gnav',
'menu_class' => 'gnav__list',
'depth' => 1,
'fallback_cb' => false,
) );
?>
<?php endif; ?>
has_nav_menu() で割り当て済みか確認すれば、未設定の場合に空の <nav> を出さずに済みます。
3. 管理画面で割り当てる
「外観 > メニュー」でメニューを作成し、「メニューの設定」の表示場所にチェックします(ブロックテーマでは別の画面になります)。コードで作るなら、wp_create_nav_menu()、wp_update_nav_menu_item()、set_theme_mod( 'nav_menu_locations', ... ) を使います。
動作確認(検証環境と結果)
WordPress 7.1.2(ja)、PHP 8.2.12 の CLI 環境で、一時メニューを作成して確認し、終了時に削除しました。
- 登録直後、
has_nav_menu( 'primary' )はfalse。 - 未割り当てで
wp_nav_menuを呼ぶと、<div class="menu"><ul><li class="page_item ...">サンプルページ</li></ul></div>(固定ページ一覧)が返った。 fallback_cb => falseではfalse(出力なし)。- メニューを作成して
primaryに割り当てると、has_nav_menu( 'primary' )はtrue、footerはfalse。 container => 'nav'、menu_class => 'gnav__list'、depth => 1で、<nav class="gnav"><ul id="menu-p1-tmp-menu" class="gnav__list">...が出力された。- 削除後、
wp_get_nav_menu_objectはfalse。
ログは testsadd-navigation-menu-theme-register-nav-menus.md にあります。ブラウザでの管理画面操作は、この環境では行っていません。
テーマにナビゲーションメニューを追加する方法の注意点
register_nav_menus()は、テーマ機能の宣言としてafter_setup_themeにまとめて書くのが一般的です(after_setup_theme フックの使い方|説明・引数・注意点参照)。公式リファレンスのユーザー投稿ノートにはinitで呼ぶ例もあり、どちらでも動作します。- メニューの割り当て(
nav_menu_locations)はテーマごとに保存されるため、テーマを切り替えると割り当てが外れることがあります。 containerに使えるのは、既定ではdivとnavです。- ブロックテーマでは、ナビゲーションブロックを使うため、この手順は不要な場合があります。
テーマにナビゲーションメニューを追加する方法でよくあるミス
- 位置を登録しただけで、管理画面で割り当てない。
theme_locationの名前が、登録時と違う(primaryとmainなど)。- 位置名(スラッグ)を後から変更し、割り当て済みのメニューが表示されなくなる(公式にも注意書きあり)。子テーマで扱うときは子テーマと functions.phpも参照。
$html = wp_nav_menu( ... )と変数に入れて加工しようとして、echo => falseを指定し忘れる。既定(echo => true)では、その場で出力され、戻り値は値を持ちません(検証ではNULL)。
テーマにナビゲーションメニューを追加する方法のチェックリスト
- [ ]
register_nav_menus()をafter_setup_themeで呼んだか - [ ]
theme_locationの名前が一致しているか - [ ] 管理画面で位置に割り当てたか
- [ ]
fallback_cbの方針を決めたか - [ ]
depthやクラス名がデザインと合っているか
テーマにナビゲーションメニューを追加する方法のFAQ(よくある質問)
Q. メニューが空のとき、何も出したくありません。
A. fallback_cb => false にするか、has_nav_menu() で囲みます。
Q. メニューのHTMLを細かく変えたいです。
A. walker を渡す方法と、nav_menu_css_class などのフィルターを使う方法があります。
Q. 複数の位置を登録するのに、関数は1つで足りますか?
A. register_nav_menus() に連想配列で渡せば足ります。
筆者の見解(テーマにナビゲーションメニューを追加する方法)
メニューの不具合は、コードより「割り当て忘れ」であることが多いと考えます。まず has_nav_menu() で状態を確かめ、その上で fallback_cb を false にしておくと、未設定のときの挙動が分かりやすくなります。納品時には、位置の名前と割り当て手順を、簡単にでもまとめておくと親切だと思います。
テーマにナビゲーションメニューを追加する方法の関連項目
- register_nav_menus() の使い方|説明・引数・注意点
- wp_nav_menu() の使い方|説明・引数・注意点
- after_setup_theme フックの使い方|説明・引数・注意点
- add_theme_support() の使い方|説明・引数・注意点
- get_template_part() の使い方|説明・引数・注意点
