WordPressでカスタムタクソノミーやカスタムフィールドによる絞り込み検索を実装する方法をご紹介いたします。
以前、「チェックボックスによる絞り込み検索を実装する方法」や「セレクトボックスによる絞り込み検索を実装する方法」で絞り込み検索の実装方法を書きました。これらは、search.php内でquery_postsを使ってメインクエリを書き換えて検索結果を表示する方法でしたし、カスタムフィールドには触れていませんでした。
今回は、search.phpはいじらずにpre_get_postsというフックを使った方法で、さらにカスタムフィールドにも対応した絞り込み検索の実装方法をご紹介いたします。
カスタムタクソノミーやカスタムフィールドによる絞り込み検索を実装する方法
絞り込み検索用のフォームを設置
まずは、絞り込み検索のフォームを設置します。今回は以下のようなフォームを設置します。
- カテゴリー:チェックボックスによる選択
- カスタムタクソノミー:セレクトボックスによる選択
- サイズ(カスタムフィールド):セレクトボックスで最小値と最大値の範囲指定
- 価格(カスタムフィールド):セレクトボックスで最小値と最大値の範囲指定
- 投稿タイプ:通常の投稿のみ
- キーワード検索:なし
フォームを設置したい箇所に、コードを追加します。
<form action="<?php echo esc_url(home_url('/')); ?>" method="get">
<input type="hidden" name="s">
<input type="hidden" name="post_type" value="post">
<h3>カテゴリーから探す</h3>
<ul>
<?php
$categories = get_terms('category', 'hide_empty=0');
foreach ($categories as $cat) :
$cat_name = $cat->name;
$cat_slug = $cat->slug;
?>
<li><input type="checkbox" id="<?php echo esc_attr($cat_slug); ?>" name="cat[]" value="<?php echo esc_attr($cat_slug); ?>"><label for="<?php echo esc_attr($cat_slug); ?>"><?php echo esc_html($cat_name); ?></label></li>
<?php
endforeach;
?>
</ul>
<h3>カスタムタクソノミーから探す</h3>
<select name="customtax">
<option value="">指定なし</option>
<?php
$customtax = get_terms('customtax', 'hide_empty=0');
foreach ($customtax as $tax) :
$tax_name = $tax->name;
$tax_slug = $tax->slug;
?>
<option value="<?php echo esc_attr($tax_slug); ?>"><?php echo esc_html($tax_name); ?></option>
<?php
endforeach;
?>
</select>
<h3>サイズから探す</h3>
<select name="min_size">
<option value="">指定なし</option>
<option value="10">10cm</option>
<option value="20">20cm</option>
<option value="30">30cm</option>
<option value="40">40cm</option>
<option value="50">50cm</option>
</select>
<p>~</p>
<select name="max_size">
<option value="">指定なし</option>
<option value="10">10cm</option>
<option value="20">20cm</option>
<option value="30">30cm</option>
<option value="40">40cm</option>
<option value="50">50cm</option>
</select>
<h3>価格から探す</h3>
<select name="min_price">
<option value="">指定なし</option>
<option value="100">100円</option>
<option value="200">200円</option>
<option value="300">300円</option>
<option value="400">400円</option>
<option value="500">500円</option>
<option value="1000">1000円</option>
</select>
<p>~</p>
<select name="max_price">
<option value="">指定なし</option>
<option value="100">100円</option>
<option value="200">200円</option>
<option value="300">300円</option>
<option value="400">400円</option>
<option value="500">500円</option>
<option value="1000">1000円</option>
</select>
<button type="submit">検索</button>
</form>
キーワード検索はなくても「name=”s”」のinputは必須なので「type=”hidden”」で入れています。これがないと検索結果が表示できません。
また、「name=”post_type”」のvalueで投稿タイプを指定しています。複数の投稿タイプを指定したい場合は、以下のように配列として渡します。
<input type="hidden" name="post_type[]" value="post">
<input type="hidden" name="post_type[]" value="page">
検索結果に絞り込み条件を反映
続いて、適用しているテーマのfunctions.phpに以下を追記して、検索結果ページで絞り込み条件を反映させて表示します。
function my_refine_search($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_search()) {
//絞り込み検索のクエリを変数に格納
$s = $_GET['s'];
$post_type = $_GET['post_type'];
$cat = $_GET['cat'];
$customtax = $_GET['customtax'];
$min_size = intval($_GET['min_size']);
$max_size = intval($_GET['max_size']);
$min_price = intval($_GET['min_price']);
$max_price = intval($_GET['max_price']);
//投稿タイプの指定
if (!empty($post_type)) {
$query->set('post_type', $post_type);
}
//カテゴリー
if (!empty($cat)) {
$cat_selected = array(
'taxonomy' => 'category',
'terms' => $cat,
'field' => 'slug',
'operator' => 'IN'
);
}
//カスタムタクソノミー
if (!empty($customtax)) {
$customtax_selected = array(
'taxonomy' => 'customtax',
'terms' => $customtax,
'field' => 'slug',
'operator' => 'IN'
);
}
//サイズ
if (!empty($min_size) || !empty($max_size)) {
$size_selected = array(
'key' => 'size',
'value' => array($min_size, $max_size),
'type' => 'NUMERIC',
'compare' => 'BETWEEN'
);
}
//価格
if (!empty($min_price) || !empty($max_price)) {
$price_selected = array(
'key' => 'price',
'value' => array($min_price, $max_price),
'type' => 'NUMERIC',
'compare' => 'BETWEEN'
);
}
//カテゴリーとカスタムタクソノミーの絞り込み検索条件
if (
!empty($cat_selected)
|| !empty($customtax_selected)
) {
$tax_query = array(
array(
'relation' => 'AND',
$cat_selected,
$customtax_selected
)
);
}
//カスタムフィールドの絞り込み条件指定
if (
!empty($size_selected)
|| !empty($price_selected)
) {
$meta_query = array(
'relation' => 'AND',
$size_selected,
$price_selected
);
}
//絞り込み検索の場合はクエリを指定
if (
!empty($tax_query)
|| !empty($meta_query)
) {
$query->set('s', $s);
$query->set('tax_query', $tax_query); //タクソノミーの絞り込み条件
$query->set('meta_query', $meta_query); //カスタムフィールドの絞り込み条件
$query->set('posts_per_page', 10); //表示件数
}
}
}
add_action('pre_get_posts', 'my_refine_search');
GETパラメータから各種情報を取得して、タクソノミーの検索条件はtax_queryへ、カスタムフィールドの検索条件はmeta_queryへと渡しています。これにより、フォームで選択した条件に合致する投稿のみが表示されます。
また、カスタムフィールドは範囲検索なので、compareの値をBETWEENにしています。
あとがき
一見複雑そうに見えて、やっていることは意外とシンプルです。
上記はあくまで一例なので、タクソノミー名やカスタムフィールドの値などについては、サイトの環境に合わせて調整してください。