WordPressに絞り込み検索を実装する【プラグイン無し】
プラグインを使用せずに、フリーワード、カテゴリー、タグで絞り込み検索を実装する方法を紹介します。
絞り込み検索は”WP_Query”のパラメーター、”tax_query”を活用するのがポイントです 。
【事前準備】タクソノミー(カテゴリー)名を検索できるようにしておく
WordPressデフォルトではカテゴリー名はフリーワードで検索できず…事前準備として対策しておきます。 手っ取り早くプラグインを使用する方法と、functions.phpに記述する方法、両方書いておきますね。
方法1 プラグインを使用する
“WP Extended Search”プラグインを使用します。
方法2 functions.phpに記述する
SQL文を使用してカテゴリー名を検索しています。
function my_custom_search($search, $wp_query) {
global $wpdb;
if (!$wp_query->is_search)
return $search;
if (!isset($wp_query->query_vars))
return $search;
$search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : '');
if ( count($search_words) > 0 ) {
$search = '';
foreach ( $search_words as $word ) {
if ( !empty($word) ) {
$search_word = '%' . esc_sql( $word ) . '%';
$search .= " AND (
{$wpdb->posts}.post_title LIKE '{$search_word}'
OR {$wpdb->posts}.post_content LIKE '{$search_word}'
OR {$wpdb->posts}.ID IN (
SELECT distinct tr.object_id
FROM {$wpdb->term_relationships} AS tr
INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN {$wpdb->terms} AS t ON tt.term_id = t.term_id
WHERE t.name LIKE '{$search_word}'
OR t.slug LIKE '{$search_word}'
OR tt.description LIKE '{$search_word}'
)
OR {$wpdb->posts}.ID IN (
SELECT distinct post_id
FROM {$wpdb->postmeta}
WHERE meta_value LIKE '{$search_word}'
)
) ";
}
}
}
return $search;
}
add_filter('posts_search','my_custom_search', 10, 2);
とりあえずコード全部
「searchform.php」が検索フォーム、「search.php」が検索結果を表示するテンプレートになります。「search.php」の下部でget_search_form() 関数で「searchform.php」を読み込んでおり、結果ページでも検索フォームを表示して再検索できるようにしています。
searchform.php
<form role="search" method="get" id="searchform" action="<?php echo esc_url(home_url('/')); ?>">
<h2>カテゴリー</h2>
<?php
$category_args = array(
'orderby' => 'name',
'order' => 'ASC',
);
$categories = get_terms( 'category', $category_args );
foreach($categories as $category) :
?>
<label><input type="checkbox" name="get_cats[]" value="<?php echo $category->slug; ?>"><?php echo $category->name; ?></label>
<?php endforeach; ?>
<h2>タグ</h2>
<?php
$post_tag_args = array(
'orderby' => 'name',
'order' => 'ASC',
);
$post_tags = get_terms( 'post_tag', $post_tag_args );
foreach($post_tags as $post_tag) :
?>
<label><input type="checkbox" name="get_tags[]" value="<?php echo $post_tag->slug; ?>"><?php echo $post_tag->name; ?></label>
<?php endforeach; ?>
<h2><?php _x( 'Search for:', 'label' ); ?>キーワード</h2>
<input type="text" value="<?php echo get_search_query(); ?>" name="s" id="s" placeholder="キーワードを入力してください" />
<input type="submit" value="検索" />
</form>
search.php
<?php get_header(); ?>
<?php
$s = $_GET['s'];
$get_cats = $_GET['get_cats'];
$get_tags = $_GET['get_tags'];
if($get_cats) {
$tax_ary[] = array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => $get_cats,
'operator' => 'IN', //ANDかIN
);
}
if($get_tags) {
$tax_ary[] = array(
'taxonomy' => 'post_tag',
'field' => 'slug',
'terms' => $get_tags,
'operator' => 'IN', //ANDかIN
);
}
?>
<?php if (!($s || $get_cats || $get_tags)): ?>
<p>検索条件を指定してください</p>
<?php get_search_form(); ?>
<?php else: ?>
<h1>検索結果</h1>
<?php
if(is_array($get_cats)) {
echo '<p>カテゴリー:';
foreach ($get_cats as $val) {
$p_term = get_term_by('slug', $val, 'category');
echo $p_term->name;
if ($val !== end($get_cats)) {
echo ', ';
}
}
echo '</p>';
} ?>
<?php
if(is_array($get_tags)) {
echo '<p>タグ:';
foreach ($get_tags as $val) {
$s_term = get_term_by('slug', $val, 'post_tag');
echo $s_term->name;
if ($val !== end($get_tags)) {
echo ', ';
}
}
echo '</p>';
} ?>
<?php
if($s) { echo '<p>キーワード:'.$s.'</p>'; } ?>
<?php
$my_query = new WP_Query( array(
'paged' => get_query_var('paged'),
'post_type' => 'post',
'tax_query' => $tax_ary,
'relation' => 'AND', //ANDかOR
's' => $s,
)); ?>
<?php if($my_query->have_posts() ) : ?>
<ul>
<?php while( $my_query->have_posts()) : $my_query->the_post(); ?>
<li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
</li>
<?php endwhile; ?>
</ul>
<?php else: ?>
<p>結果が見つかりませんでした。</p>
<?php endif; ?>
<?php get_search_form(); ?>
<?php endif; ?>
<?php get_sidebar(); ?>
<?php get_footer(); ?>
searchform.phpの解説
カテゴリー、タグの情報をget_terms関数で取得、foreachループでformのチェックボックスとして 一覧出力しています。
キーワード欄は通常の検索と同じ記述です。
カスタムタクソノミーやカスタム投稿の場合は?
get_terms( $taxonomies, $args )の$taxonomiesの部分にカスタムタクソノミー名を指定します。
$categories = get_terms( 'category', $category_args );
↓↓↓
$taxonomies = get_terms( 'my_taxonomy', $taxonomy_args );
また、検索範囲をカスタム投稿に限定したい場合はformタグのactionのURIにカスタム投稿名(post_type)を指定します。
<form role="search" ... action="<?php echo esc_url(home_url('/')); ?>my_post/">
search.phpの解説
まず冒頭の$_GETで検索フォームでチェックされた項目及びフリーワードを取得しています。
$s = $_GET['s'];
$get_cats = $_GET['get_cats'];
$get_tags = $_GET['get_tags'];
もし何もチェックが無く、フリーワードも入力されていない場合は「検索条件を指定してください」というメッセージを出力します。
入力があれば、検索結果を表示します。
<?php if (!($s || $get_cats || $get_tags)): ?>
<p>検索条件を指定してください</p>
<?php get_search_form(); ?>
<?php else: ?>
<h1>検索結果</h1>
//~省略~
<?php endif; ?>
チェックした項目とフリーワードを表示します。
この部分は無くてもいいのですが、検索条件を表示してあげる方が親切だと思います。
<h1>検索結果</h1>
<?php
if(is_array($get_cats)) {
echo '<p>カテゴリー:';
foreach ($get_cats as $val) {
$p_term = get_term_by('slug', $val, 'category');
echo $p_term->name;
if ($val !== end($get_cats)) {
echo ', ';
}
}
echo '</p>';
} ?>
<?php
if(is_array($get_tags)) {
echo '<p>タグ:';
foreach ($get_tags as $val) {
$s_term = get_term_by('slug', $val, 'post_tag');
echo $s_term->name;
if ($val !== end($get_tags)) {
echo ', ';
}
}
echo '</p>';
} ?>
<?php
if($s) { echo '<p>キーワード:'.$s.'</p>'; } ?>
WP_Queryを使って検索結果を取得します。
‘tax_query’パラメータ―には、チェックしたカテゴリーとタグを指定します。
冒頭の$_GETで取得しましたよね。
パラメータ―’s’はフリーワードです。
後はループで検索結果の投稿一覧を出力しています。
カスタムタクソノミーやカスタム投稿の場合は?
カスタムタクソノミーの場合は’tax_query’の’taxonomy’パラメータ―の部分にカスタムタクソノミー名を指定します。
$tax_ary[] = array(
'taxonomy' => 'my_taxonomy', ...
);
AND / OR検索
カテゴリーやタグ同士の場合は、’tax_query’の’operator’にANDかIN(OR)で指定、カテゴリーとタグ間の場合はWP_Queryの’relation’にANDかORを指定します。
ソースコードにコメントを付けていますので確認してみてくださいね。