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
- css
処理の順序
- PHPの処理
- 検索窓テンプレートの作成
- ナビに検索ボタンの追加
- 検索ページの作成
- その他の処理
- モーダル
- CSS(scss)
PHPの処理
検索窓テンプレートの作成
まず、前提としてWordPressで検索フォームを表示する際は、
searchform.php
をget_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, id
にs
がありますが、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ライフを!