[WordPress]ナビゲーションメニューの投稿をウィジェットを使ってサムネイル付きでリスト表示


WordPressでブログ等を運用する際に、いくつかの記事をピックアップしてサイドバーなどに表示したいと感じることがあると思います。

もちろんそういったプラグインは豊富にありますが、せっかく「ナビゲーションメニュー」や「ウィジェット」といった便利機能が備わっているので、今回はそれらを使いプラグインなしで実装しようと思います。


## 仕様

- ピックアップする記事は「ナビゲーションメニュー」機能で選ぶ
- ウィジェットを使って任意の場所に表示する
- 記事のサムネイルやカテゴリー情報なども表示する

ウィジェットに「ナビゲーションメニュー」を追加するのはデフォルトでも可能ですが、そのままだとタイトルしか表示されません。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/e7788bbd-7c3a-7766-a60a-c4d7dd13c277.png" alt="デフォルトのナビゲーションメニュー表示例" width="1280" style="outline : 3px solid #efefef;">

これでは味気ないので、サムネイルやカテゴリー情報など一通り記事の情報も表示できるように設定します。

## 前準備

ダッシュボードから「外観 ＞ メニュー」ページへ移動し、ナビゲーションメニューを作成し、ピックアップする記事をメニューに追加します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/935914e0-9e31-4c2e-e47c-37ee50bac462.png" width="1306" alt="ダッシュボードからメニュー作成">

「投稿」から記事をピックアップし、「メニューに追加」ボタンで追加してください。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/58b0b007-f292-a27a-0bfe-8a990e70bd10.png" alt="記事をピックアップし、メニューに追加" width="1280">

「メニューを保存」ボタンを押し忘れないようにしてください。


## コード

### function.php

テンプレートディレクトリ内の ```function.php``` に

1. ナビゲーションメニュー用のウィジェットエリア
2. メニュー名から表示するナビゲーションメニューを選ぶ関数

を追加するため以下のコードを記入してください。

```function.php``` がない場合は新しくファイルを追加してください。


```php:function.php
// ウィジェットを追加
register_sidebar();

if (function_exists('register_sidebar')) {
  register_sidebar(array(
    'name' => 'ピックアップ記事',
    'id' => 'pickup_posts',
    'before_widget' => '<div>',
    'after_widget' => '</div>'
  ));
}

// ナビゲーションメニュー名から記事を取得する関数
function showNavPosts($menu_name) {

  // ナビゲーションメニュー名を指定
  $menu = wp_get_nav_menu_object( $menu_name );

  // ウィジェット情報を取得
  $widget_nav_menus = get_option('widget_nav_menu');

  foreach ($widget_nav_menus as $key => $widget_data) {
    if(is_array($widget_data) && $widget_data['nav_menu']) {
      $widget_id = $widget_data['nav_menu'];

      /* ウィジェットに該当するナビゲーションメニューを設定しているかを確認し
         設定があればナビゲーションメニューをリスト表示する
      */
      if($widget_id == $menu->term_id) {
      ?>
    <h4><?php
    // ウィジェットのタイトル
    echo $widget_data['title'];
    ?></h4>
      <?php

        // ▼ここから ナビゲーションメニューの記事を取得・表示
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        foreach ( (array) $menu_items as $key => $menu_item ) {
          $post_id    = $menu_item->object_id;
          $content    = get_post($post_id);

          $post_title   = $menu_item->title;
          $post_url     = $menu_item->url;
          $categories   = $content->post_category;
          $post_content = wp_html_excerpt($content->post_content);
          $post_thumbail  = get_the_post_thumbnail_url($post_id, 'thumbnail');
          ?>
          <div class="media mt-3">
            <a href="<?php echo $post_url; ?>">
              <img class="d-flex mr-3" src="<?php echo $post_thumbail; ?>" alt="">
            </a>

            <div class="media-body">
              <h5 class="mt-0">
                <a href="<?php echo $post_url; ?>"><?php
              // 記事タイトルを表示
              echo $post_title;
              ?></a>
              </h5>

              <?php
              // カテゴリーを表示
              if($categories) {

              echo '<p>';

                foreach ($categories as $category_id) {
                  $category   = get_category($category_id);
                  $category_name  = $category->cat_name;

                  // カテゴリーの区切り
                  if($category_id != reset($categories)) {
                    echo ' / ';
                  }

                  echo $category_name;
                } // foreach

              echo '</p>';

              } // if
              // ここまで/カテゴリーを表示
              ?>
              <p><?php
              // 本文
              echo wp_html_excerpt($post_content, 40, '…');
              ?></p>
            </div>
          </div>
          <?php
        } // foreach $menu_items
        // ▲ここまで / ナビゲーションメニューの記事を取得・表示


      } // if
    } // if
  } // foreach
} // showNavPosts
```

htmlタグ部分はbootstrapのメディアオブジェクトを参考にしていますが、好きにコーディングしてください。

▼参考 Bootstrap
https://getbootstrap.com/docs/4.0/layout/media-object/

記事の情報（タイトル、URL、カテゴリーなど）は ```get_post``` で取得しているので、日付や投稿者など他に必要な情報があれば「get_post」で検索すれば取得方法が見つかります。


### テンプレートファイル

サイドバーやフッターなど、任意のテンプレートファイルにメニューを表示するためのコードを記入します。


```php:sidebar.php
<?php
// ウィジェットの取得&関数呼び出し
// function.php で設定したウィジェットID
if ( is_active_sidebar( 'pickup_posts' ) && function_exists('showNavPosts') ) :
?>

<div class="widget-area" role="complementary">
<?php showNavPosts('pickup'); ?>
</div><!-- .widget-area -->

<?php
// ここまで / ウィジェットの取得&関数呼び出し
endif;
?>
```

## ウィジェットを追加

ダッシュボードから「外観 ＞ ウィジェット」ページへ移動し、「ナビゲーションメニュー」を選択し ```function.php``` で追加したウィジェットエリア「ピックアップ記事」に追加します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/1ebca675-cb6a-67c7-985c-7071cab93b47.png" alt="ウィジェットページからナビゲーションメニューを選択" width="680.5">

「ピックアップ記事」エリアにナビゲーションメニューのウィジェットが追加されたので、

- タイトル
- 表示したいメニュー

を記入もしくは選択します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/f3b8217a-6d76-2fe5-17d7-c946d04c2c81.png" alt="" width="1118">

これでナビゲーションメニューが追加されました。


## 結果

サイドバーにナビゲーションメニューに追加した記事のリストが表示されました。
サムネイルや本文など、表示内容をカスタマイズできるのでデフォルトの「ナビゲーションメニュー」ウィジェットより使えるのではないでしょうか。

<img src="https://qiita-image-store.s3.amazonaws.com/0/62022/27e86191-b6dd-6939-bfa7-7784a831eca8.png" alt="サイドバー表示例" width="1225" style="outline : 3px solid #efefef;">

以上になります。
参考になりましたら幸いです。

---

下記のページを参考にしました。

▼関数リファレンス/wp get nav menu items - WordPress Codex 日本語版
https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_get_nav_menu_items#.E3.83.87.E3.83.95.E3.82.A9.E3.83.AB.E3.83.88.E3.81.AE.E4.BD.BF.E3.81.84.E6.96.B9