トップへ戻る
BLOGS

WordPress 条件絞り込み検索機能を実装します(プラグインなし)

WordPress 条件絞り込み検索機能を実装します(プラグインなし)

さあ、

今回は、最近学習した内容の集大成として

「条件絞り込み検索機能」を制作していこうと思います

今回はブログでの実装となりますが、他の種類、たとえば商品や不動産情報など

様々なニーズに対応できる使用としております

ではまず前提条件や実装内容を定義していきます

検索概要

  • カスタム投稿タイプにて使用しているブログ記事を絞り込む
  • 内容としてはすべてのタームを出力し、チェックを入れていく形式
  • タクソノミーはカテゴリーとタグ
  • 表示するページはブログのアーカイブ(一覧)ページ

機能概要

  • 絞り込む内容はタクソノミーごとに分けてチェックを入れてもらう
  • アーカイプページの先頭にトグルスイッチを置いて、クリックすると絞り込み検索コンテンツがモーダルで表示する
  • 最初は通常のループを回しておく
  • 絞り込み検索をサブミットするとその検索結果で記事が並ぶようにする
  • 枠組みとして大きいカテゴリーの条件は「またわ」とする
  • タグの絞り込み条件は詳細なので「かつ」でしぼる

今回作るのはこんな感じですね

割と大掛かりなコードになりそうなので、さらにここからもプログラムを書くためのルートもしっかりと考察、洗い出しておこうと思います

最初に訪れた際
  • アーカイブを通常通り表示する
  • 検索フォームを表示
  • チェックボックスをタクソノミーごとに全て表示する
  • 検索のメソッドはPOSTにする
条件を入力して検索
  • サブミット後は同じページに返ってくるようにする
  • 入力された値はPOST変数に格納し条件分岐させる
  • 入力された内容(チェック)を保持する
  • wp_queryの値に入力された内容を反映させる
  • 新規ループ処理を回し、条件にマッチしない処理も仕込んでおく

こんな感じですかね

ではまず順に実装していきます

通常のループを回す

<?php
      $args = array(
        'post_type'      => 'blogs',
        'post_status'    => 'publish',
        'posts_per_page' => -1,
        'orderby'        => 'date',
        'order'          => 'DESC'
      ); ?>


     //この中で条件を追加する処理を書いていく

    <?php
      $the_query = new WP_Query($args);
      if($the_query->have_posts()) :
      while($the_query->have_posts()) :
      $the_query->the_post();
      get_template_part('template-parts/loop','post_cade');
      endwhile; wp_reset_postdata(); //ループ終わり
      else : ?>
      <p>該当する記事は見つかりませんでした。</p>
      <?php endif; ?>

はい。ここまではよく見るカスタム投稿用のループ処理のテンプレートですね

このテンプレートのパラメータ指定の箇所とループを回すWP_Queryの間に条件を入れれるようにしてWP_Query のパラメータを書き換えていきます

まず必要なのは入力するフォームですね、

入力フォームを整える

<form method="POST" action="<?php echo esc_url(home_url() . $_SERVER['REQUEST_URI']); ?>">
 <h2 class="condition-title">カテゴリーで絞り込む</h2>
     <div class="condition">
         //カテゴリーチェックボックス
     </div>

 <h2 class="condition-title">タグで絞り込む</h2>
     <div class="condition">
        //タグのチェックボックス
     </div>
 <input type="submit" value="チェックされた記事を表示する" class="submit-button">
</form>

まずフォームタグを用意して値を送信できるようにします

そしてその送信メソッドにmethod=”POST”としてPOSTを指定します

さらに送信ボタンを押された際に起こるaction属性には、

home_url()でトップページまでのURLを、

$_SERVER[‘REQUEST_URI’]で現在のページのディレクトリを指定しています

それをURLとしての値として整え、テキストや属性などのURLを無害化する時に用いる関数。esc_url()でエスケープして、このページに戻ってくるようにしています、

$_SERVER['REQUEST_URI']は正確には現在リクエストされているディレクトリのURLを返すようです。

この後pagenaite_linksなどでページネーションをつける際は、フォームタグのaction属性には、直接現在のページのURLを指定して下さい。

そしてページネーションをつける際にはリクエストメソッドもPOSTではなくGETで送信してください。

2021/5/29追記

ターム情報を取得してループさせる

get_terms (‘タクソノミー名’,’配列かパラメータ’)

$cat_terms =  get_terms('oja_cat',array(
         'hide_empty' => false,
         'orderby' => 'slug',
        ));

‘hide_empty’ => false,こちらのパラメータをfalseか0で指定することで投稿が一つもないタームを出力します、ついでに並び順の指定もしました

取得した配列変数をforeachで出力します

ループ処理でチェックボックスを生成

<input type="checkbox" name="search_cat[]" value="<?php echo esc_attr($cat->slug;) ?>"><?php echo esc_html($cat->name); ?>

まず説明したい箇所は、

ネーム属性の箇所でname=”search_cat[]”として[]を付けることでチェックボックスの値を配列として受け取ることが可能です

つまり通常チェックボックスのname属性はバラバラにしなければならず、同じにしてしまうと送信される値はたったの一つになってしまうのですが、配列としてすべての値を受け取りそれを送信することですべての値を受け取れるという仕組みです

そして送信される値のvalue属性はesc_attr($cat->slug;)とループ中のスラッグを入れることで出力します

esc_attrはいわゆる記号などの 文字をエンコードします。

スラッグは日本語で書いてますし下手な記号が入るとエラーになりかねないので

alt、value、title などの HTML 要素(特にフォーム値)をエスケープする場合は必ず使用してください。

esc_html($cat->name);そして最後にタームの名前を同じ様にエスケープしてHTML関数で出力してあげます

この記述法でタグの方も同じ様に書いてあげましょう

次は送信された際の挙動を実装します、

POSTで送られた値をチェックして変数にしておく

if(!empty($_POST['search_cat'])) {
    foreach ($_POST['search_cat'] as $value) {
      $search_cat[] = htmlspecialchars($value,ENT_QUOTES,'UTF-8');
    }
  }

サブミットされた値はグローバル変数$_POSTに格納されているため

if(!empty($_POST[‘search_cat’]))とすることで確認ができます

PHP関数empty()は変数が存在していたらtrueになる関数なので!マークを付けて反転させることでif文の中に入ります

そしてその変数からループ処理で中の値を用意した配列変数に代入します

htmlspecialchars($value,ENT_QUOTES,’UTF-8′)

こちらはメールやログインページによく使用しますね、受け取った値($value)を無害な文字列へとサニタイズしてくれる関数です  $value以外はテンプレートとして覚えておきましょう

入力されたチェックを保持しておく

検索してみて、気に入った記事がなければ再検索したいと思うはずです

一度チェックを入れた項目はページ遷移してもチェックが入ったままにしてあげるのが親切です

checkboxのタグはセレクトなどと同じ様にchecked属性を付けると最初からチェックが入った状態になります

これを利用してPHPの条件分岐を書きます、

具体的には$_POSTがあった時に同じ項目にPHPでchecked属性を記述します

$checked = '';
        if(in_array($cat->slug, $search_cat, true)) {
          $checked = ' checked';
        }

in_array(検索する値、 配列、型まで一致させるかどうか)

こちらの関数で入力された値と一致するスラッグのタグにcheckedがつけれるようにします

そしてHTMLのタグにも追記します

<input type="checkbox" name="search_cat[]" value="<?php echo esc_attr($cat->slug); ?>" <?php echo esc_attr($checked); ?>><?php echo esc_html($cat->name); ?>

<?php echo esc_attr($checked); ?>でさっき変数に入れたcheckedが出力されます  チェックを入れていない項目は条件に入らないため空文字列のままです

検索された値をパラメータに指定する

さてもう一息ですね

ここからは検索して受け取った値をWP_Query のパラメータとして渡してあげます

まずはそれぞれを同じ様に変数に入れます

$tax_args[] = array(
      'taxonomy' => 'oja_tags',
      'terms'    => $search_tag,
      'field'    => 'slug',
      'operator' => 'AND',
    );

‘operator’ => ‘AND’,は絞り込む条件です  タグに関しては全てのタグ条件が一致するという指定のため‘AND’にしていますがカテゴリーは広く含まれるという指定をするため‘IN’を指定します

taxonomyはそれぞれのスラッグをしてしてあげて

termsの項目に作成した配列変数を入れます

それではパラメータ指定します

if(!empty($search_cat) || !empty($search_tag)) {
    $args += Array('tax_query' => array($tax_args));
  }

上記の指定でどちらかの変数が存在していたら、というif文となります

‘tax_query’ => array($tax_args)タックスクエリーの指定の仕方はもともと配列指定なのでこちらでもarrayとして渡してあげます

これで一通りのギミックを実装できました

長いコードでしたがお疲れ様でした

次回はこのコンテンツにCSSやJSで装飾しますか

コメントをお待ちしております

お気軽にコメントをどうぞ。

CAPTCHA