WordPressの wp_nav_menu を思い通りにカスタマイズする

WordPressの独自テーマでトップページのメニューリストに外部リンク先を簡単に追加できるように変更して欲しいという依頼が来ました。簡単にメニューに追加する方法で対応しますと返事したのですが、wp_nav_menu テンプレートタグが曲者で不要なdiv等のタグやid、classを出力して思い通りに変更ができませんでした。

まずメニューの入力フォームにある説明を使用したいのでどのように表示するか検索したところこの記事を見つけることが出来ました。このコードを利用してさらにliに不要なidとclassを消しかつ連番のidを追加しliタグの中に必要なコードやタイトル、説明を追加するコードを書いてみました。

$id_no = 1;
add_filter( 'nav_menu_css_class', 'filter_menu_li' );
function filter_menu_li(){
      return array('');   
}

add_filter('nav_menu_item_id','change_nav_menu_id',10,2); 
function change_nav_menu_id($current_id,$item_details){ 
      global $id_no; return 'id_' .$id_no++; 
}

add_filter('walker_nav_menu_start_el', 'description_in_nav_menu', 10, 4);
function description_in_nav_menu($item_output, $item){
      return preg_replace('/(<a.*?>)(.*?<\/a>)/', "<div class='index-cat'>" . '$1' . "<i class='icon-circle icon-large'></i></a></div><div class='index-cat-text'><div class='index-cat-title'>{$item->title}</div><div class='index-cat-description'>{$item->description}</div></div>", $item_output);
}

通常は上記のコードをfunctions.phpに追加します。今回は、トップページにのみ適用したいのでindexページのテンプレートに追加しました。
reg_replaceでは、aタグに囲まれたコードを置換しますが、必要なコードを追加した後にaタグを展開させその後必要なコード、タイトル、説明を追加しています。タイトルは{$item->title}、説明は{$item->description}で表示できました。もう少し簡単に置換出来るかもしれませんが正しく表示できたので良しとします。

さらに表示したいテーマの中(今回はindexページのテンプレート)にwp_nav_menuのオプションを指定して配置します。オプションでは不要なdiv、ulタグを削除しています。

<?php wp_nav_menu( array('menu' => 'outer link', 'container' => '', 'items_wrap' => '%3$s')); ?>

これでwp_nav_menuを思い通りにカスタマイズ出来ました。