Bootstrap Ver.4のナビゲーションメニューをWordPressのカスタムメニューとして実装する

Bootstrapに実装されている”Navbar”を使うと、モバイルにも対応したナビゲーションメニューを簡単に作ることが出来ます。

今回は、この”Navbar”をWordPressのカスタムメニューとして出力させる方法について、自身へのメモも兼ねて書き残しておきます。

なお、サブメニューは第一階層までの出力に対応しています。Bootstrapの標準仕様ではありますが、さらに深い階層も表示できる仕様への対応も検討しています。

実装コード

テーマ

<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
  <div class="container">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
  
    <div class="collapse navbar-collapse" id="navbarsExampleDefault">
    <ul class="navbar-nav mr-auto">

<?php
    /* メニュー項目を配列として取得 */
    $menu_name = 'menu-1';  // 定義したメニュー名
    $locations = get_nav_menu_locations();
    $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
    $item = wp_get_nav_menu_items( $menu->term_id, array( 'order' => 'DESC' ) );

    $submenu = false;
    $dropdown_id = 0; // ドロップダウン制御用
    $item_length = count($item);

    for($i = 0; $i < $item_length; $i++){

      // タイトルとURLを取得
      $title = $item[$i]->title;
      $link  = $item[$i]->url;

      // 親を持たない項目(サブメニューの項目ではない)場合
      if ( !$item[$i]->menu_item_parent ){

        // 後でサブメニューの項目と比較する為にIDを保存しておく
        $parent_id = $item[$i]->ID;
?>
<?php
        // 次に現れる項目が、サブメニューの項目であれば、このメニューリンクはトグルリンクにする
        if($i < $item_length - 1 && $parent_id == $item[$i + 1]->menu_item_parent){
?>
          <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="<?php echo $link; ?>" id="dropdown<?php echo $dropdown_id ?>" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><?php echo $title; ?></a>
<?php
        } else {
?>
          <li class="nav-item<?php if($item[$i]->object_id == get_queried_object_id()) echo ' active'; ?>">
          <a class="nav-link" href="<?php echo $link; ?>"><?php echo $title; ?></a>
<?php
        }
      }
?>      
<?php
      // 参照中項目の親IDが、直前に保存しておいたIDと一致している場合
      if ( $parent_id == $item[$i]->menu_item_parent ){
        // サブメニューの項目の出力を開始する
        if ( !$submenu ){
          $submenu = true;
?>
          <div class="dropdown-menu" aria-labelledby="dropdown<?php echo $dropdown_id ?>">
<?php
        }
        //サブメニューを書く
?>
        <a class="dropdown-item" href="<?php echo $link; ?>"><?php echo $title; ?></a>
<?php
        // 次の項目が同じ親IDを持たず、サブメニューが宣言状態である場合は、サブメニューを閉じる
        if ($i < $item_length - 1 &&  $item[$i + 1]->menu_item_parent != $parent_id && $submenu ){
?>
          </div>
<?php
          $submenu = false;
          $dropdown_id++;
        }
      }

      // 次の項目が同じ親IDを持たない場合は、<li>を閉じます
      if ($i < $item_length - 1 && $item[$i + 1]->menu_item_parent != $parent_id ){
?>
        </li>
<?php
      } else if ($i == $item_length - 1){
?>
        </li>
<?php
      }
    } //END of loop
?>
    </ul>
    </div>
  </div>
</nav>

functions.php

// メニューに標準で出力されるIDを削除する
function removeId( $id ){
  return $id = array();
}
add_filter('nav_menu_item_id', 'removeId', 10);

// メニューのaタグにbootstrapのクラスを追加
function add_class_on_link($item_output, $item){
  return preg_replace('/(<a.*?)/', '$1' . " class='nav-link'", $item_output);
}
add_filter('walker_nav_menu_start_el', 'add_class_on_link', 10, 4);

// カレントページでは該当するメニューにclassを追加
function remove_to_currentClass( $classes, $item ) {
  $classes = array();
  $classes[] = 'nav-item';
  if( $item -> current == true ) {
    $classes[] = 'active';
  }
  return $classes;
}
add_filter( 'nav_menu_css_class', 'remove_to_currentClass', 10, 2 );

参考文献

php – ワードプレスのwp_get_nav_menu_itemsを使ってカスタムメニューサブメニューシステムを生成するにはどうすればいいですか? – コードログ

タイトルとURLをコピーしました