WordPressでメディアサイトを運営していると「検索」が必要になってきます。

特に記事数が多いサイトですと尚更です。

ですが、サイドバーに置くとSP時に下の方までスクロールしないと気づかれません。

そのため、ナビゲーションの最後に検索ボタンを追加してみます。

今回の方法では「外観->メニュー」は使用せず、
WordPressのhookであるwp_nav_menu_objectsを使用します。

wp_nav_menu_objectsを使用することで、
データベースに依存せずに「検索」を追加することができるからです。

それでは、やっていきましょう!

# この記事で解決すること

  • wp_nav_menuで呼び出したメニューの最後に検索ボタンを追加できる
  • データベースに依存せずに検索ボタンを追加できる

前提

追加方法がhookを使用するため、functions.phpないし、
custom-functions.phpを編集できる必要があります。

「外観->メニュー」で登録したメニュー名に依存しますので、
同じメニュー名のものが複数箇所設定されていた場合、双方に反映されることになります。

フォルダ構成

  • theme_name
    • css
      • style.css(scss)
    • template
      • parts-search_modal.php
    • functions.php
    • search.php

 

処理の順序

  • PHPの処理
    • 検索窓テンプレートの作成
    • ナビに検索ボタンの追加
    • 検索ページの作成
  • その他の処理
    • モーダル
    • CSS(scss)

PHPの処理

検索窓テンプレートの作成

まず、前提としてWordPressで検索フォームを表示する際は、
searchform.phpget_search_form()で呼び出すというのが一般的
です。

今回は別の方法を取っていますが、上記でも問題ありません。

template/parts-search_modal.php

<div class="menu-search__btn">
  <span class="icon-search">
    <!-- 検索icon -->
  </span>
</div>
<div class="menu-search__modal">
  <div class="menu-search__modal__inner">
    <p class="menu-search__title">キーワード検索</p>
    <form method="get" id="searchform" class="menu-search__form" action="<?php echo esc_url(home_url()) ?>">
      <div class="menu-search__form__wrap">
        <input type="text" name="s" id="s" placeholder="キーワード検索">
      </div>
      <div class="menu-search__form__wrap">
        <button type="submit">検索</button>
      </div>
    </form>
    <div class="menu-search__modal__btn">
      × 閉じる
    </div>
  </div>
</div>

1~5行目

ナビゲーションに表示させる箇所です。

<!-- 検索icon -->の箇所は任意のアイコンやテキストなどに置き換えてください。

6行目以降はModalです。

9行目

home_url()getアクションを送ります。

11行目

name, idsがありますが、Wordpressの検索ではこのクエリに文字列を送ります。

 

ナビに検索ボタンの追加

今回はheader-navというナビゲーションに対してアクションをおこしていきます。

functions.php

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

// 変数格納用テンプレート取得
function get_template_var( $root, $file )
{
  ob_start();
  get_template_part( $root, $file );
  return ob_get_clean();
}

// header-navに「search追加」
function add_search_header_nav( $items, $args )
{
  if($args->menu === 'header-nav') {
    $contents = get_template_var( 'template/parts', 'search_modal' );
    foreach( $items as &$item ) {
      if($item === end($items)) {
        $item->title = "{$item->title}</a></li><li class='menu-search'>{$contents}</li>";
      }
    }
  }
  return $items;
}

1行目

フック先はwp_nav_menu_objectsです。

詳しくはリファレンスをご覧ください。

4~9行目

get_template_partの戻り値は変数に格納できないため、
格納できるように予め関数を作成しておきます。

14行目

$args内にナビゲーションの情報がありますので、
header-navの場合にのみ限定し処理を行います。

これがないと、別のナビゲーションの場合にも処理されることになります。
(ex: footer-nav etc…)

15行目

先程作成しておいた関数を使用して$contents
template/parts-search_modal.phpの情報を格納しておきます。

16行目

$item->titleを直接書き換える必要があるので、
foreachにある$itemのまえに&をつけています。

&をつけることで、ループオブジェクトの値を操作することができます。

17行目

ナビゲーションの最後に検索ボタンをつけたいのでend($items)と比較しています。

18行目

ここは少し無理やりなのですが、
</a></li>で一つ前の$itemを無理やり閉じて、新たにリストを付け加えています。

 

検索ページの作成

検索結果が表示されるページも作成する必要があります。

archive.phpをコピーして作成すれば早いです。

ここでは、最低限必要な部分だけ紹介します。

search.php

<?php get_header(); ?>

<?php if ($_GET['s']): ?>
  <?php if(have_posts()): ?>
    <?php while (have_posts()) : the_post(); ?>
      <!-- 記事一覧テンプレート -->
    <?php endwhile; ?>
  <?php else: ?>
    <p>指定検索ワード「<b><?php echo $_GET['s'] ?></b>」で記事が見つかりませんでした。</p>
    <p>当該記事は削除されたか移行された可能性があります。</p>
  <?php endif; ?>
<?php else: ?>
  <p>検索ワードが未入力です。</p>
<?php endif; ?>

<?php get_footer(); ?>

3行目

検索フォームにもあったsのクエリを取得し、検索ワードが空白でなければ処理を、
空白だと検索ワードが未入力であることをユーザーに表示します。

4行目

検索ワードに引っかかった記事が取得されている状態ですので、そのままループを回せば良いです。

9, 10行目

検索ワードに記事が引っかからなかった場合の文言も表示してあげると
ユーザーに優しいサイトになるでしょう。

タイトルの調整

検索ページでタイトル部分に検索した文字列を表示したいときがありますよね。

そういう場合は、header.phpなどで下記を参考に条件分岐し、
検索した文字列を表示してあげると良いでしょう。

// 検索ページの場合
if(is_search()) { hoge... }

// 検索した文字列
$_GET['s']

 

ここまででPHP側の処理は完了です!

次にcss, js周りを追加していきます。

その他の処理

モーダルの実装

モーダルの実装と言っても特に難しいことはしません。

検索ボタン(.menu-search__btn)を押したら
モーダル(.menu-search__modal)にonが付与され、
閉じる(.menu-search__modal__btn)を押したら
先程付与したonが外れるといった処理にします。

ですので、動きの部分はcssで制御する形になります。

本来ならjsファイルを用意して、切り分けたいのですが、
簡単な処理なのでparts-search_modal.phpの最下部に追記しておきます。

template/parts-search_modal.php

<script>
(function($){
  $('.menu-search__btn, .menu-search__modal__btn').on('click', function(){
    $('.menu-search__modal').toggleClass('on')
  }
})(jQuery);
</script>

久々のjQuery+挙動確認してないので動くか不安ですが、多分動きます。

cssの処理

あとは、適当にcssをあてればOKです!

css/style.scss

.menu-search {
  &__modal {
    text-align: center;
  }
  &__btn {
    display: none;
  }
}

@media screen and (min-width: 1024px) {
.menu-search {
  &__btn {
    cursor: pointer;
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background-color: #000;
    color: white;
    font-size: 1.5rem;
    transition: .3s background-color linear;
    span {
      line-height: 0;
    }
    &:hover {
      background-color: #eee;
    }
  }
  &__modal {
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: 100;
    transform: translate(-50%, -50%) scale(0);
    opacity: 0;
    filter: blur(100vw);
    display: grid;
    place-items: center;
    width: 100vw;
    height: 100vh;
    background-color: rgba(#eee, .95);
    transition:
      .2s .4s transform ease-in,
      .2s .4s filter ease-in,
      .4s 0s opacity ease-in;
    &.on {
      transform: translate(-50%, -50%) scale(1);
      opacity: 1;
      filter: blur(0);
    }
    &__inner {
      position: relative;
      text-align: center; 
    }
    &__btn {
      cursor: pointer;
      margin-top: 2rem;
      color: white;
      font-weight: bold;
    }
  }
}
}

@media screen and (max-width: 1023px) {
.menu-search {
  display: contents;
  &__modal {
    width: 100%;
    margin-top: 2rem;
    padding-top: 2rem;
    border-top: 1px solid white;
    &__btn {
      display: none;
    }
  }
}
}

 

最後に

wp_nav_menu_objectsを使用すれば、ナビゲーションの最後に任意の項目を追加できることがわかったのではないでしょうか。

特に検索ボタンは、管理画面上で操作することもないと思いますので、wp_nav_menu_objectsでの実装が最適解なのではと思っています。

今回は検索ボタンでしたが、ボタン以外にも任意のテキストやコンテンツを追加することも可能です。

また、カンの良いあなたはお気づきかもしれませんが、メガメニューの実装にも使用できます。

みなさんもwp_nav_menu_objectsを駆使してWorpressをカスタマイズしてみてください~

それでは、よいWPライフを!