wp_get_nav_menu_items()はmenu_orderとmenu_item_parentを分けて並び順と親子関係を読む
公開日: 執筆:佐藤
wp_get_nav_menu_items()は、指定したnavigation menuの項目をmenu_order順の配列で返します。返り値は階層化されたtreeではありません。親子関係は各項目のmenu_item_parentを使って組み立てます。
項目自身のIDはdb_id、リンク先となる投稿やtermのIDはobject_idです。順番、親子関係、項目ID、リンク先IDを同じ数字として扱わないでください。
関数へ渡すのはmenuの名前、ID、slugである
WordPress 4.0のwp_get_nav_menu_items()は、第一引数からnavigation menuのobjectを探します。第一引数にはmenuの名前、ID、slugを渡せます。menuが見つからなければfalse、menuが空なら空の配列を返します。
theme locationの識別子は、menuの識別子とは別です。たとえば、themeがprimaryというlocationを登録し、管理画面で「会社案内」というmenuを割り当てているとします。これは説明用の仮例です。primaryをそのままwp_get_nav_menu_items()へ渡しても、「会社案内」の項目を取得する指定にはなりません。
locationから取得する場合は、get_nav_menu_locations()で割り当てられたmenu IDを確認します。
$locations = get_nav_menu_locations();
if ( empty( $locations['primary'] ) ) {
return;
}
$items = wp_get_nav_menu_items( $locations['primary'] );
if ( false === $items ) {
return;
}
locationが未割り当ての場合と、割り当て先のmenuを取得できない場合を分けています。空のmenuは正常な空配列なので、falseと同じ扱いにしません。
menu_orderは表示順でmenu_item_parentは親項目のIDである
既定の取得条件では、公開状態のnav_menu_itemがmenu_orderの昇順で返ります。ただし、配列が平坦であることは変わりません。子項目が配列の中へ入れ子になるわけではありません。
主なpropertyは次の役割を持ちます。
| property | 表すもの | 混同しやすい対象 |
|---|---|---|
menu_order |
menu内の表示順 | 親子の深さではない |
menu_item_parent |
親となるnav menu itemのID | 元の投稿の親IDではない |
db_id |
nav menu item自身のID | リンク先の投稿IDではない |
object_id |
元の投稿またはtermなどのID | nav menu item自身のIDではない |
url |
項目が示すURL | menuの管理画面URLではない |
title |
menu項目に表示する文字列 | 元の投稿titleと常に同じとは限らない |
たとえば、固定ページをmenuへ二か所配置すると、二つのnav_menu_itemは異なるdb_idを持てます。どちらも同じ固定ページを指すなら、object_idは同じです。項目ごとに表示名や親を変えられるため、削除や並べ替えではdb_idを使い、リンク先の内容を調べる場合はobject_idを使います。
親子関係はmenu_item_parentをkeyにして組み立てる
独自の出力や一覧データが必要なら、取得済みの順番を保ちながら、menu_item_parentごとに項目をまとめます。
$children = array();
foreach ( $items as $item ) {
$parent_id = (int) $item->menu_item_parent;
if ( ! isset( $children[ $parent_id ] ) ) {
$children[ $parent_id ] = array();
}
$children[ $parent_id ][] = $item;
}
親を持たない項目は$children[0]に入ります。その項目のdb_idをkeyとして、次の階層を探せます。配列の直前にある項目を親だと推測しないため、同じ階層で並び替えても関係を保てます。
再帰処理でHTMLを出す場合は、存在しない親ID、循環、深すぎる階層でも処理を止められるようにします。処理したdb_idを記録し、同じ項目を二度たどらないようにします。
通常のmenu表示にはwp_nav_menu()を使う
headerやfooterへ通常のnavigationを表示するだけなら、独自にwp_get_nav_menu_items()を回す前にwp_nav_menu()を使います。theme_location、表示する階層、walker、前後のmarkupなどをまとめて指定できるからです。
wp_nav_menu(
array(
'theme_location' => 'primary',
'depth' => 2,
)
);
wp_get_nav_menu_items()が必要になるのは、menu項目を別形式のデータへ変換する場合や、通常のwalkerでは表せない処理を行う場合です。関数を直接使うことを目的にせず、必要な出力を先に決めます。
無効な項目と出力時のescapeを確認する
WordPress 4.0の処理は、公開画面で無効と判定されたmenu項目を返り値から除きます。管理画面ではこの除外処理が行われないため、管理画面と公開画面で項目数が違う場合があります。
独自にHTMLを作るなら、urlをesc_url()、表示するtitleをesc_html()などで出力時に処理します。取得済みの値だから安全だと決めつけません。menuを編集できる利用者、外部から取り込んだ値、filterで変更された値を含め、出力する文脈に合わせます。
menuの出力を外部へ委託しても、theme location、割り当てるmenu、親子関係、編集できる利用者はサイト運営側で記録します。template codeだけでは、管理画面でどのmenuを割り当てるべきか残りません。
最初の一手は、取得したい対象がmenuそのものか、theme locationかを確定することです。locationなら割り当てmenuのIDを取得し、返された一項目についてmenu_order、menu_item_parent、db_id、object_idを並べて確認してください。
関連記事

