[WordPress]検索画面にターム一覧のチップを追加・検索対象にする

概要

テキストボックスでの検索の他に日付検索とタームを選択しての検索を追加する必要があった。
検索は特定のポストタイプでのみ動作する。
全部フック「pre_get_posts」の中に書いて、if ( $query->is_search() )で検索結果だけに反映しています。

add_action( 'pre_get_posts', 'customize_main_query' );
function customize_main_query($query) {
  if ( is_admin() || ! $query->is_main_query() )
    return;
    //ゴニョゴニョ………
}

ターム一覧

ポイントは下記

  1. 検索フォーム内で、チェックボックスのnameはcat[]とかcategory[]とか、[]で終わらせる。
    こうすると後でURLパラメータを配列に格納した時に勝手にこの項目が配列になる。
  2. functions.php内でパラメータをGETしてループを加工することで投稿の呼び出しへ反映させる。

検索テンプレート、検索を実装するテンプレートではinputタグのチェックボックスを用いてタームの選択肢を追加。

functions.phpでは、URLを元にパラメータの中身を配列として取り出し、tax_queryでタクソノミーとタームを指定する。
ターム名を配列にしてタームの指定に用いる。

参考URL:
【PHP】URLを分解して配列で取り出すには?(Web.fla)

functions.php

//URL取得
if ( isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on' )  
{  $protocol = 'https://';  }  
else  
{  $protocol = 'http://';  }
$search_url  = $protocol.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];  
//念のためデコード
$decoded_url = urldecode($search_url);
//URLを配列に分解
$url_arr = parse_url($decoded_url);
//パラメータの中身を文字列の配列として変数へ格納
parse_str($url_arr['query'], $parms);
//タクソノミー指定
if ( ! empty( $parms['category'] ) && !is_wp_error( $parms['category'] ) ){
  $query->set('tax_query' , array(
    array(
      'taxonomy' => 'タクソノミー名',
      'field' => 'slug',
      'terms' => $parms['category'] //フォームで取得した値
      )
    )
  );
}

ちなみにこれを作ってるときまで気づかなかったけどfunctions.php内で普通に$protocol.$_SERVER[‘HTTP_HOST’].$_SERVER[‘REQUEST_URI’]でURLを取得しようとしても実行タイミングが早すぎてサイトURLしか取れません。pre_get_postsのタイミングだから取れてるだけ。

検索するテンプレートのフォーム部分

<ul class="term-list">
<?php
  $terms = get_terms('タクソノミー名',
    //オプションは必要に応じて
    array(
      'parent' => 0,
      'orderby' => 'description'
    )
  );
  //投稿が存在するタームの一覧を取得・加工
  if ( ! empty( $terms ) && !is_wp_error( $terms ) ):
  foreach( $terms as $term ):
?>
  <li>
    <label class="term-item"><input name="category[]" type="checkbox" value="<?php echo $term->slug; ?>"><span><?php echo $term->name; ?></span></label>
  </li>
<?php endforeach; endif; ?>
</ul>

日付検索の実装

jQueryUIのDatepickerで入力した値を、検索結果のループを加工する時に利用する。
基準となる日付は投稿日ではなくてカスタムフィールドに入力された日付の値を利用しているのでちょっとややこしかった。

$date_from_src = $_GET["date_from"]; //この日から
$date_until_src = $_GET["date_until"]; //この日まで

if( $date_from_src != '' && $date_until_src != '' ){
  //始めも終わりも指定した場合
  $query->set(
    'meta_query', array(
      'relation' => 'AND', //AND検索にする
      array(
        'key' => 'カスタムフィールド名',
        'value' => $date_from_src,
        'compare'=>'>=',
        'type' => 'DATE'
      ),
      array(
        'key' => 'カスタムフィールド名',
        'value' => $date_until_src,
        'compare'=>'<=',
        'type' => 'DATE'
      )
    )
  );
} elseif( $date_from_src != '' && $date_until_src == '' ){
  //始めだけ指定した場合
  $query->set(
    'meta_query', array(
      array(
        'key' => 'カスタムフィールド名',
        'value' => $date_from_src,
        'compare'=>'>=',
        'type' => 'DATE'
      )
    )
  );
} elseif( $date_from_src == '' && $date_until_src != '' ){
  //終わりだけ指定した場合
  $query->set(
    'meta_query', array(
      array(
        'key' => 'カスタムフィールド名',
        'value' => $date_until_src,
        'compare'=>'<=',
        'type' => 'DATE'
      )
    )
  );
}