wp_nav_menu カスタムメニューにメタデータを埋め込む
wp_nav_menu 関数はカスタムメニューを表示するための関数(テンプレートタグ)です。 メニューの前後に表示する(HTML)テキストを指定したり、メニューを覆うラッパーの要素を指定するなど、細かな制御が可能です。
しかしながら、schema.org が提唱するような、itemprop などを用いたメタデータを埋め込むための機能は用意されていません。 nav_menu_item_id などのフィルタにフックすれば、class 名や id 名を細かく制御することができますが、 いずれの方法でも、class 名や id 名以外を設定することはできません。
したがって、メニューに関する独自のデータや、あるいはメタデータを埋め込みたい場合には、 wp_nav_menu 関数が出力する HTML テキストを独自にカスタマイズする必要があります。
幸いなことに wp_nav_menu 関数は、独自の HTML テキストを出力するための機能を備えています。 パラメータ walker に対し、独自に実装するクラスを指定することで、メタデータの埋め込みなどが可能になります。
ここでは schema.org の提唱するメタデータ SiteNavigationElement を埋め込む例を示します。
wp_nav_menu - Codex 日本語版wp_nav_menu 関数の設定
先に wp_nav_menu 関数の設定について解説しておきます。 ここで解説されない項目や詳細については公式のページを確認してください。
<nav class="site-navigation main-navigation" role="navigation"
itemscope itemtype="http:\/\/schema.org/SiteNavigationElement">
wp_nav_menu
(array('theme_location' => '設定したメニューのスラッグ',
'container' => false,
'items_wrap' => '<ul>%3$s</ul>',
'walker' => new Karakuri_Walker_Nav_Menu));
</nav>
wp_nav_menu の設定
container パラメータ に false を指定して、div や nav などのラッパーを出力しないようにします。 代わりに schema.org のSiteNavigationElement メタデータを埋め込んだ nav 要素を任意に追加します。
items_wrap パラメータには、出力するメニューの一番外側の要素を指定します。
このとき、%3$s
の記述を忘れないようにします。ここに具体的なメニュー (li 要素) が挿入されます。
nav 要素ではなく、ここで指定する ul 要素に itemscope や itemtype を指定するのも手だと思います。
最後に指定する walker パラメータが重要です。 walker には、具体的なメニューを出力するクラス Walker_Nav_Menu を指定します。 標準のメニューを出力する Walker_Nav_Menu クラスではなく、 独自のメニューを出力する Walker_Nav_Menu を指定します。
Walker_Nav_Menu クラスの実装(定義)
標準の Walker_Nav_Menu クラスは、./wp-includes/nav-menu-template.php ファイルの中に定義されています。 この Walker_Nav_Menu` クラスを継承したクラスを実装します。
"継承" はプログラミングする際に用いられる用語なので、WordPress などのみを触っている人には理解しにくいかもしれません。 ちょうど CSS の継承の概念を想像すれば良いのですが、端的には、元々あった機能を引き継いだ、わずかに変更された機能を作ることを継承と言います。
ここでは、標準の Walker_Nav_Menu クラス(の機能)を引き継いだ、別の Walker_Nav_Menu を作ることになります。 新たに作る Walker_Nav_Menu を仮に Custom_Walker_Nav_Menu とします。
次のコードが schema.org のメタデータを埋め込む Custom_Walker_Nav_Menu クラスです。
functions.php など、wp_nav_menu
関数が参照できる場所(ファイル)に定義します。
class Custom_Walker_Nav_Menu extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args)
{
$output .= '<li itemprop="name" class="menu-item">';
$item_output .= '<a itemprop="url" href="'
. esc_attr($item -> url) .'">'
. $item -> title . '</a>';
$output .= apply_filters('walker_nav_menu_start_el',
$item_output,
$item,
$depth,
$args);
}
}
schema.org を埋め込む Walker_Nav_menu
Walker_Nav_Menu クラスには他にもいくつかの関数(機能)がありますが、"継承" しているので、 Custom_Walker_Nav_Menu クラスでは改めてそれらの関数を作る必要がありません。
start_el
関数だけが元の機能を書き換えています。
元の関数(機能)を書き換えるためには、関数名を一致させる必要があるので注意してください。
同じ関数名で上書きすることを、プログラミング用語では、関数のオーバーライドと呼びます。
start_el
関数は、li 要素を出力する関数です。
したがって、ここで schema.org のメタデータを埋め込むことができます。
schema.org のメタデータについてはここでは解説しません。
<li itemprop="name" class="menu-item">
のように、
独自のデータが埋め込まれていることが分かると思います。
wp_nav_menu
関数では、before や after などのパラメータが定義されます。
それらは、$args -> before
や $args -> after
のようにして取得することができます。
汎用的な Walker_Nav_Menu を作るためには、それらを出力に追加する必要がありますが、
ここでは簡単に説明するために省略しています。
理想的な出力結果の例
ここで実装した Custom_Walker_Nav_Menu クラスを使った理想的なカスタムメニューの例を示します。 例えば、テンプレートファイル内で次のようにカスタムメニューを出力させます。
<nav class="site-navigation main-navigation" role="navigation">
<?php
wp_nav_menu
(array('theme_location' => '設定したメニューのスラッグ',
'container' => false,
'items_wrap' => '<ul itemscope itemtype="http:\/\/schema.org/SiteNavigationElement">%3$s</ul>',
'walker' => new Custom_Walker_Nav_Menu));
?>
</nav>
wp_nav_menu
出力結果は次の通りです。
<nav class="site-navigation main-navigation" role="navigation"
itemscope itemtype="http:\/\/schema.org/SiteNavigationElement">
<ul>
<li itemprop="name" class="menu-item">
<a itemprop="url" href="URL">メニュータイトル</a>
<ul class="sub-menu">
<li itemprop="name" class="menu-item">
<a itemprop="url" href="URL">サブメニュータイトル</a>
</li>
</ul>
</li>
</ul>
</nav>
Custom_Walker_Nav_Menu から出力された美しい HTML
紹介する都合上、出力結果を整形しています。出力されるソースコードを適切にインデントしたい場合には、
start_el
関数の引数 $depth を使って、メニューの深度に応じてインデントするコードを出力します。
SiteNavigationElement のマークアップ方法について
schema.org の提唱する SiteNavigationElement の指定方法については、執筆時時点(2015.06)では明らかにされていません。
単に SiteNavigationElement だけを指定し、itemprop="name"
や itemprop="url"
を指定しない、という見方もあります。
状況に応じて、適宜更新するなどしてください。
ここで紹介する方法は、Google の構造化テストツールではエラーが起きませんでした。 一方で、メタデータとして正しい構造であるか、正しい意味を伝えられているのかどうか、は不明です。