WordPress:メニューにアイコンを使う(Walker_Nav_Menu)

WordPress:メニューにアイコンを使う(Walker_Nav_Menu)

現在、WordPress のテーマ制作を一からつくる方法と Genesis Framework を使った方法の二刀流でやっています。

01Genesis ではデフォルトでアイコンが使える

下のリンクがはてなブログから WordPress に移行したサイトですが、メニューに Dashicons のアイコンを使っています。

そんなには褒めないよ。映画評 – ネタバレレビュー・あらすじ

このサイトは Genesis Framework の子テーマで作っており、外観 > メニュー > カスタムリンク のリンク文字列にアイコンタグを入れれば何もしなくてもアイコンが表示されます。

たとえば、

<svg class="dashicons dashicons-category" role="img"><use xlink:href="/wp-includes/fonts/dashicons.svg#menu-alt" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>

と入れれば、ハンバーガーメニューアイコンが表示されます。

なお、dashicons の svgファイルを使ってアイコンを表示させる方法は「WordPress:SVGファイルでDashiconsを表示する」をご覧ください。

02WordPress デフォルトではタグがエスケープされる

ところが、WordPress デフォルトで同じようにアイコンタグを入れますと下の画像のように文字列にエスケープされ(この表現であってるか?)アイコンになりません。

03Walker_Nav_Menu を使ってメニューにアイコンを表示する

Genesis については最後まで調べてはいませんが、結局 Genesis はメニュー表示に「テンプレートタグ/wp nav menu」を使っていないのでないかという考えにいたり、じゃあデフォルトの WordPress でタグを文字列に変えてしまうフィルターを回避できないかと調べ、wp_nav_menu のパラメータ walker に Walker_Nav_Menu を上書きするクラスを指定すればいいということがわかりました。

wp_nav_menu の walker パラメータ

wp_nav_menu( array(
    'theme_location' => 'primary-menu',
    'container' => '',
    'menu_class' => 'menu menu-primary',
    'link_before' => '<span itemprop="name">',
    'link_after' => '</span>',
    'walker' => new custom_walker_nav_menu,
));

walker パラメータに Walker_Nav_Menu を上書きする custom_walker_nav_menu クラスを指定します。

Walker_Nav_Menu の上書きクラス

Walker_Nav_Menu クラスにある

$title = apply_filters( 'the_title', $menu_item->title, $menu_item->ID );

で、htmlタグが文字列に変換されてしまいますので、そのフィルターを回避するようクラスを書き換えます。

class custom_walker_nav_menu extends Walker_Nav_Menu {


    function start_el( &$output, $item, $depth, $args ) {
        // passed classes
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;
        $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
       
        // build html
        $output .= '<li id="menu-item-'. $item->ID . '" class="' . $class_names . '">';
       
        // link attributes
        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
        $attributes .= ! empty( $item->target )    ? ' target="' . esc_attr( $item->target    ) .'"' : '';
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
        $attributes .= ! empty( $item->url )        ? ' href="'  . esc_attr( $item->url        ) .'"' : '';
        $attributes .= ' class="menu-link menu-primary-link" itemprop="url"';


        
        $item_output  = $args->before;
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args->link_before . $item->title . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;
       
        // build html
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

ということで、メニューにアイコンが表示されました。なお、まだメニュー以外何もスタイルを指定していませんので文字列や画像が並んでいるだけです。