【WordPress】アーカイブページでヘッダーメニューが消える現象
タグページなどのアーカイブページでヘッダーのメニューが表示されないことがありました。
その原因と解決方法について説明します。

アーカイブページでヘッダーのメニューが表示されない原因
なぜアーカイブページで発生したのか
作成したタグページでは固定ページも一覧に表示させるために functions.php で以下のように指定していました。
// タグアーカイブに固定ページを含める
function add_page_to_tag_archive($query) {
if (is_tag()) {
$query->query_vars['post_type'] = array('post','page');
}
}
add_action('pre_get_posts','add_page_to_tag_archive');
上記は
メインクエリ(記事データ)から記事を抽出しようとして指定した条件である。
これを念頭に置き、ヘッダーメニューの生成について調べたところ以下に辿り着きました。
- サブクエリのヘッダーメニューも メインクエリと同様に WP_Query によって生成される。
- WP_Query が生成される際、データベースにクエリを投げる前に pre_get_posts 関数が呼び出される。
(pre_get_posts はメインクエリで記事を取得する前に呼び出されるアクションフック。) - 従って、ヘッダーメニューの表示時にも pre_get_posts を呼び出すので、メインクエリ用に代入した値で上書きされてしまう。
つまり、メニューを生成する際に、メインクエリから記事を一覧表示するための抽出条件で上書きしているのが原因ということです。
実際の値の変化を見ながら上記の流れを振り返ると
- サブクエリのヘッダーメニューも メインクエリと同様に WP_Query によって生成される。
var_dump($query->query_vars['post_type']);
// 実行結果: "nav_menu_item"
これは上書きされなかった場合の本来のメニューの post_type です。
- WP_Query が生成される際、データベースにクエリを投げる前に pre_get_posts 関数が呼び出される。
(pre_get_posts はメインクエリで記事を取得する前に呼び出されるアクションフック。) - 従って、ヘッダーメニューの表示時にも pre_get_posts を呼び出すので、メインクエリ用に代入した値で上書きされてしまう。
var_dump($query->query_vars['post_type']);
/* 実行結果: "array(2) {
[0]=>
string(4) "post"
[1]=>
string(4) "page"
}"*/
メニューの post_type がメインクエリの抽出条件で上書きされてしまいました。
アーカイブページでヘッダーのメニューを表示させる方法
上記を踏まえると、タグアーカイブに固定ページを含めるために指定した条件は、メインクエリのみに適用されればよいと言うことになります。ですので、呼び出された際にメインクエリどうかの判定を行うことで回避することにしました。
メインクエリかどうかの確認できる関数。
is_main_query()
メインクエリであれば代入。
if (is_tag() && $query->is_main_query()) {
$query->query_vars['post_type'] = array('post','page');
}