技術情報

WordPressのカスタムメニューのカスタマイズ方法やプラグインのご紹介

2017.02.03


WordPressには便利な機能がいくつもありますが、CMSならではの機能として、外観の「カスタムメニュー」があります。
(管理画面の「外観」>「メニュー」で表示されるページです)

sofpblog_20170130_01

この機能は、投稿や固定ページで作成した好きなコンテンツを、マウスをドラッグして自由な順番や階層構造に並べる事ができ、これをサイト内でメニューとして表示したり、サイトマップページのようなリンク集として、表示する事が可能になります。

sofpblog_20170130_08

この記事では、カスタムメニューの固定ページとの使い方の違いや、設置方法、関係のない子ページを閉じておいたり、指定階層からの表示をしたするカスタマイズ方法をご紹介します。

カスタムメニューを利用するには

お使いのテーマを管理画面から「外観」>「メニュー」が表示されていれば、そのままカスタムメニューが使えます。

残念ながら表示されていない場合には、現在利用中のテーマがカスタムメニューを利用していないデザインテーマという事になりますが、2つのコードをテーマファイルに埋め込む事でカスタムメニューを使えるようになります。

必要なのは下記の2点です。

  1. register_nav_menusをテーマファイル内に設定する
  2. wp_nav_menuをテーマファイルの表示したい箇所に設定する

先ず、register_nav_menusを利用します。下記のコードをテーマファイル内のどこか、例えば functions.phpに追加します。

register_nav_menus( array(
     'my-menu-1' => 'カスタムメニュー1',
     'my-menu-2' => 'カスタムメニュー2',
));

このようにカスタムメニューを利用したい箇所の数だけ連想配列(array)で指定します。

これは「カスタムメニュー1」と「カスタムメニュー2」という名前で2か所にカスタムメニューを使う例です。「my-menu-1」は利用する箇所で使うスラッグ(記号)です。半角英数字で使用します。

ここで一旦管理画面をリロードすると、管理画面の「外観」に、「メニュー」が表示されるようになります。

次に、メニューから設定したページのリンクを表示させたい場合下記のコードを表示させたい場所へ入れます。

<?php wp_nav_menu(array('theme_location' => 'my-menu-1')); ?>

現在はまだ何もカスタムメニューが作られていない状態なので、下記のように「メニュー名」の入力部分に名前をつけて「メニューを作成」ボタンをクリックし、新しいメニュー構造を追加します。

sof_blog_20170205_02

次にメニューに組み込みたい固定ページや投稿記事、カテゴリー等を左の項目から選んで、「メニューに追加」ボタンをクリックし、右側の「メニュー構造」のエリアに組み込みます。

sof_blog_20170205_03

組み込んだメニューの項目は、マウスで順番を入れ替えたり、階層構造を作成したりします。

一通りメニューを組み終わったら、メニュー構造の下の「メニューの位置」でどこに表示するかをチェックして保存します。この場合先ほど定義した、my-menu-1の「カスタムメニュー1」にチェックを入れています。

sof_blog_20170205_04

固定ページとカスタムメニューの違い

階層構造をもったメニューといえば固定ページです。WordPressの固定ページはウェブサイトでは静的なページの役割を果たします。

固定ページで階層構造を指定するにはクイック編集か各ページの編集画面で「親ページ」を指定します。

sofpblog_20170130_03

同じ階層構造を作るなら、マウスのドラッグ操作でできる「カスタムメニュー」だけで階層構造を作れば良いのではと考える方もいるかもしれませんが、サイトの構造をきちんと整理しておくには、カスタムメニューより先に、この固定ページの階層化をしておく必要があります。

カスタムメニュー側で出来ない事にはurlの構造があります。

http://www.example.com/first/second/

というurlを作成する場合、固定ページでfirstとsecondというページを作成し、secondから親をfirstに設定します。

また、secondページ表示時のパン屑の表示

  home > first > second

といった表示をプラグイン等で自動表示する場合も固定ページからの階層設定になります。

あくまで、カスタムメニューは表示する上でのでパーツの作成と捉え、サイト的な階層構造
は固定ページでしっかりと作っておく必要があります。

管理画面から設定できる事

最初は表示されていないのですが、「カスタムメニュー」の管理画面で、右上の表示オプションを開くと、以下のようなメニューが表示されます。

sofpblog_20170130_06

  • タイトルの属性
    title=""の中に入る文字を指定します。
    マウスでリンクを合わせた時に、表示される文字です
  • リンクを新しいタブで開く
    指定のリンクをtarget="_blank"で別ウィンドウ表示
  • CSS クラス
    出力される<li>タグの中のclassの指定ができます。
  • 自分とリンク先の関係(XFN)
    rel=に入る文字を指定できます。例えば検索エンジンが追跡しないリンクにしたい場合nofollowを指定します。
  • 説明フィールド:
    こちらは、そのままでは入力しても何も起こりません。この入力を利用したい場合、functions.php等にコードを追加する必要があります。
    下記はタイトルのサブタイトルとして利用する例が下記の記事にあります。
    WordPressのカスタムメニュー(wp_nav_menu)を使って、サブタイトル付きのナビゲーションを実装する

現在開いているページに関係のない子ページを閉じておく

階層構造のあるメニューで、現在開いているページに関係する部分以外は閉じておきたいと考える方は多いと思います。

sofpblog_20170130_04

jqueryででアコーディオンのように隠しておいたページを表示する例は結構あるのですが、実際にhtmlタグを表示を操作する例はなかったのでご紹介します。この方法は親ページをクリックした時にきちんと親ページが表示され、WordPressの構造にあった表示ができるようになります。

下記のような、表示するメニューアイテムを制限するようなフィルター関数をwp_nav_menu_objectsにセットします。

function custom_nav_open_filter($sorted_menu_items, $args) {
    $filtered_menu = $sorted_menu_items;

    if(property_exists($args, 'relation_open') && $args->relation_open === true) {
        $open_parent_ids = array();
        $open_items = array('current-menu-parent', 'current-menu-ancestor');
        $filtered_menu = array();
        foreach ($sorted_menu_items as $i => $item) {
            if((int)$item->current === 1) {
                // 現在の開いているページ
                $filtered_menu[$i] = $item;
                $open_parent_ids[] = $item->ID;
                if ($item->menu_item_parent > 0) {
                    $open_parent_ids[] = $item->menu_item_parent;
                }
            } else if (in_array('current-menu-parent', $item->classes)
                       || in_array('current-menu-ancestor', $item->classes)) {
                // 現在のページの親を含む子孫(ancestor)
                $filtered_menu[$i] = $item;
                $open_parent_ids[] = $item->ID;
            } else if (in_array($item->menu_item_parent, $open_parent_ids)) {
                // 現在の開いているページ、関連ページの子ページ
                $filtered_menu[$i] = $item;
            } else if ((int)$item->menu_item_parent === 0 ) {
                // 第一階層
                $filtered_menu[$i] = $item;
            }
        }
    }
    return $filtered_menu;
}
add_filter( 'wp_nav_menu_objects', 'custom_nav_open_filter', 10, 2);

このフィルターはカスタムメニューが扱うメニューの各アイテムの配列を、クラス名によってフィルタリングします。

この各メニューアイテムが持つクラスは下記になります。

  • current: 現在のページ
  • current-menu-parent: 現在のページの親ページ
  • current-menu-ancestor: 現在のページの先祖(親も含む)のページ

これらを利用する事で表示するアイテムを表示を制御する事ができます。

また呼び出し側のwp_nav_menuで独自のオプション relation_open => true を指定し、フィルタリングの動作のON/OFFを制御します。

メニューを表示する部分は下記のようにします。

  <?php wp_nav_menu(array('theme_location' => 'my-menu-1', 'relation_open' => true)); ?>

実行すると下記のような形になります。

sofpblog_20170130_05

うまく動きました。

指定ページの以下の階層を表示したい

wp_nav_menuにはいろいろなオプションがありますが、wp_list_pageという固定ページのリストを表示する関数にはあるchild_ofという指定ページ以下の階層(子ページ)の表示というオプションがありません。

現在のページの子ページを、サイドに表示したりと、階層が深いサイトではとても重宝するので、このchild_ofオプションを使えるようにするカスタマイズ方法をご紹介します。

一つ前の例と同じくwp_nav_menu_objectsにフィルターをかける関数を作ります。

function custom_nav_child_of($sorted_menu_items, $args) {
    $filtered_menu = $sorted_menu_items;

    if(property_exists($args, 'child_of') && (int)$args->child_of > 0) {
        $filtered_menu = array();
        $open_parent_ids = array();
        foreach ($sorted_menu_items as $i => $item) {
            if ((int)$item->object_id === (int)$args->child_of) {
                $open_parent_ids[] = $item->ID;
            } else if(in_array($item->menu_item_parent, $open_parent_ids)) {
                // オープン親リストの子ページを登録
                $filtered_menu[$i] = $item;
                $open_parent_ids[] = $item->ID; // 表示するアイテムの子も対象にする
            }
        }
    }
    return $filtered_menu;
}

add_filter( 'wp_nav_menu_objects', 'custom_nav_child_of', 10, 2);

表示したい箇所に下記を指定します。

  <?php wp_nav_menu(array('theme_location' => 'my-menu-1', 'child_of' => 11)); ?>

sofpblog_20170130_07

固定ページID 11の下の階層から表示できるようになりました。

気を付けなければならないのは、child_of で指定しているのはお馴染みのwordpressのpost_idですが $item->IDで取得した数字は、このメニュー内での独自IDになります。

最後にカスタムメニューをつかったプラグインをいくつかご紹介します。

カスタムメニューを制御するプラグイン

カスタムメニューを改良するプラグインをいくつかご紹介します。

以上、WordPressのカスタムメニューの使い方を紹介しました。マウスで操作できるので、操作に詳しくない方でも簡単にメニュー管理ができるこの機能を是非活用してみてください。