ttt-logo 超方科技 tesseract technology tianjin

不使用插件实现多条件搜索 | 絞り込み検索をプラグインを使わずに実装

原文:https://kotori-blog.com/wordpress/refinement_search/

 

WordPressで絞り込み検索をプラグインを使用せずに実装する方法を紹介します。「Custom Fields Search」はサポート終わってる?「FE Advanced Search」はちょっと高い?大丈夫です!自分で実装してみましょう!

目次

超大作になってしまったので目次付けときます。

  1. まえがき
  2. 絞り込み検索のサンプル
  3. 絞り込み検索を実装するための土台作り
  4. キーワード検索
  5. カテゴリで絞り込むチェックボックス
  6. カテゴリで絞り込むチェックボックス以外のパーツ(プルダウン等)
  7. タグまたはカスタムタクソノミーで絞り込むチェックボックス
  8. タグまたはカスタムタクソノミーで絞り込むチェックボックス以外のパーツ(プルダウン等)
  9. カスタムフィールドで絞り込むチェックボックス
  10. カスタムフィールドで絞り込むチェックボックス以外のパーツ
  11. カスタムフィールドの値で数値比較
  12. 複数の条件を組み合わせる
  13. 検索結果ページでのページネーション

まえがき

WordPressで絞り込み検索の機能を実現させるとしたら、みなさんどうしますか?

普通はまずプラグインで手っ取り早くできないかと考えるかと思います。
プラグインで考えると真っ先に挙がるのが『Custom Fields Search』です。
この『Custom Fields Search』のいい所は無料という点です。
絞り込み検索を実装するプラグインの中で実用的かつ無料なのは『Custom Fields Search』くらいではないでしょうか。

『Custom Fields Search』は余りおススメできない

しかし、『Custom Fields Search』は余りおススメできません。
理由としては以下の点があげられます。

  • プラグインが2009年8月19日から約4年間全く更新されておらず、最近4年ぶりに更新されたが作者さんが「サポートできないのでリリースはこれが最後だろう」と宣言している。
  • inputやselectタグを含んだformタグを丸々書き出すので出力コードを自由に編集することができない。
  • W3Cのバリデータに通らない

しかし上のことが気にならなければ、非常に簡単に絞り込み検索を実現できます。
以前このKoToRi Blogでも『Custom Fields Search』の使用方法を解説しました。
もし『Custom Fields Search』を使用するなら参考にしてください。

絞り込み検索を可能にする「Custom Fields Search」[WordPress]

『FE Advanced Search』という選択肢

話が若干それましたが、絞り込み検索のプラグインでもう一つ強力なものがあります。
FE Advanced Search』です。
このプラグインはUIも分かりやすく吐き出すHTMLタグも『Custom Fields Search』よりは自由が効きそうです。
しかしこの『FE Advanced Search』には最大の欠点があります。
それは
有料 ¥59,800
という点です。

プラグインを使用しないという選択

『FE Advanced Search』の¥59,800はそうホイホイ出せる金額じゃないですね笑
でも、『Custom Fields Search』もサポート終了しています。
じゃあどうするか。

絞り込み検索はプラグインに頼らず自分で実装すればいい!

できねーよ!とか思わないでください。案外簡単だったりします。KoToRiはプログラマじゃないしphpのスキルもそこまで高くないですがWordPressでの絞り込み検索は実装できました。WordPress3.1から追加された「tax_query」と「meta_query」を駆使すれば、絞り込み検索はそんなに難しくないのです。

まえおきが長くなってしまいましたが、この記事では絞り込み検索機能をプラグインに頼らず自分で実装する方法を紹介していこうと思います。

絞り込み検索のサンプル

とりあえずKoToRiが作ったプラグインを使用しない絞り込み検索のサンプルをご覧ください。

プラグインに頼らず実装する絞り込み検索のサンプル
Googleに引っかかっちゃうとよろしくないのでアクセス制限を掛けています。
下記情報でログインしてください。

ユーザー名 admin
パスワード kotori

絞り込み検索といったら不動産サイトでしょ!!ということで不動産サイトを想定したサンプルとなっています。

WordPress絞り込み検索で一般的に考えられるパーツはこんなところではないでしょうか。

  • キーワード検索
  • カテゴリで絞り込むチェックボックス
  • カテゴリで絞り込むチェックボックス以外のパーツ(プルダウン等)
  • タグまたはタクソノミーで絞り込むチェックボックス
  • タグまたはタクソノミーで絞り込むチェックボックス以外のパーツ(プルダウン等)
  • カスタムフィールドの値で絞り込むチェックボックス
  • カスタムフィールドの値で絞り込むチェックボックス以外のパーツ(プルダウン等)
  • カスタムフィールドの値で数値比較(サンプルでいうところの家賃のフィールド)

チェックボックスとそれ以外で分けているのはチェックボックスは値が配列で返ってくるため扱いが違ってくるためです。
上に挙げた機能を実装することができれば大体のシチュエーションには対応できるかと思われます。(多分)
この記事では上に挙げた項目を全部解説していきます。

また、このサンプルはカスタムフィールドは「Custom Field Template」、カスタムタクソノミーは「Custom Post Type UI」を使用して作成しています。未だ使ったことが無い方は是非試してみてください。ラクチンです。

Custom Field Templateの使い方[WordPress]
Custom Post Type UIの使い方[WordPress]

2014年03月10日 追記
キーワード検索の検索対象にカスタムフィールドを含めたい場合は「Search Everything」プラグインを利用しましょう。下記を参考にしてください。
カスタムフィールドをサイト内検索の対象にする「Search Everything」[WordPress]

2017年07月09日 追記
「Search Everything」プラグインのバージョンアップにより、本記事で紹介している絞り込み検索が正常に動作しなくなる現象が確認されました。どうしても「Search Everything」プラグインを使用する場合は下記バージョンをお試しください。(もうちょい新しいのでもイケるかも!?)
search-everything.8.0.zip

それでは絞り込み検索の実装を解説していきます。

絞り込み検索を実装するための土台作り

検索ボタンが押されたら、必ず検索結果ページを表示する

何言ってんだ、当たり前だろ。と思われるかもしれませんがこれ重要です。

WordPressのキーワード検索の場合、ユーザーが入力した検索キーワードを「s」に格納し$_GETで投げます。キーワード検索で検索ボタンを押すと遷移先のURLに「?s=○○」の形式で文字列が追加されるのですがそれです。
これは基本ですね。

WordPressはこの「s」に値が入っているときに「検索結果ページ(search.php)」を表示します。

逆に考えると「s」に値が無かったら「検索結果ページ」が表示されません。
もしサンプルのように、キーワード検索と組み合わせて他の項目でも絞り込みできるようにした場合、そのままだと検索キーワードに必ず何か入れないと検索結果ページが表示されないということになります。

絞り込み検索を実装する場合は、まずこの現象を回避する必要があります。

お使いのテーマのfunctions.phpに以下のコードを追加してください。

1
2
3
4
5
6
function custom_search($search, $wp_query  ) {
    //query['s']があったら検索ページ表示
    if ( isset($wp_query->query['s']) ) $wp_query->is_search = true;
    return $search;
}
add_filter('posts_search','custom_search', 10, 2);

2014年4月8日 コード修正

上記のfunctionを追加するとキーワードを入力せずに「検索」ボタンを押した時もsearch.phpが表示されるようになります。

参考:WordPressのサイト内検索の検索条件をカスタマイズする

2015年2月26日 追記
なんかWordPress4.0以降から空文字検索でもsearch.phpが表示されるようになってるらしいです!!とはいえ公開してるサンプルサイトはWordPressのバージョンが4.01なのですが上記のコードをfunctions.phpに書いて正常に機能しています。
なので、お使いのWordPressのバージョンが4.0以降の人は、最初にfunctions.phpにコード追加しない状態で空文字検索で動作確認して、もしダメなら上記のコードを追加してみてください。

参考:WordPress 4.0 から、空文字の検索に対する挙動が変わったようです

2015年3月03日 追記
上のコードを追加してもsearch.phpが表示されない場合は、下記のコードも試してください。
WordPress3.0くらいだとこっちのコードじゃないと動かないかもです。
いよかんさんコメントありがとうございます!

1
2
3
4
5
6
7
function search_no_keywords() {
if (isset($_GET['s']) && empty($_GET['s'])) {
include(TEMPLATEPATH . '/search.php');
exit;
}
}
add_action('template_redirect', 'search_no_keywords');

検索ボタンが押されると、「s」に値が入っているか入っていないかを判定して入っていない場合は「””(ダブルクォーテーション2つ)」を代入する処理を行います。
こうすることにより、キーワードが空の場合でも検索結果ページを表示してくれるようになります。

検索結果ページのtitle

みなさん「All in One SEO Pack」使ってますか?
「All in One SEO Pack」の設定がデフォルトの状態だと検索結果ページのtitleが「検索キーワード|サイト名」という形になります。
しかし、そのままだと検索キーワードを入れずに検索した場合のtitleが「””|サイト名」と意味不明なことになってしまいます。
ということで検索結果ページのtitleの設定を変えてあげましょう。

検索結果ページのタイトルを変更

2014年12月12日 コード修正

WordPress4.01にバージョンアップしたら検索キーワードに何も入力しないで検索結果ページを表示させた場合、「All in One SEO Pack」で設定したタイトルが表示されないようでした。(もしかしたら初めからそうだったのかも><)
同じ現象が起こる方はtitleタグに下記を追加してください。

1
<title><?php if(is_search()){ ?>検索|プラグインに頼らず実装する絞り込み検索のサンプル<?php } ?></title>

これで検索結果ページはコード上に入力したタイトルが、その他のページは「All in One SEO Pack」で設定したタイトルが表示されるはずです。

検索フォームの基本パーツ

念のためおさらいです。
WordPressの検索フォームの基本はこのコードでしょう。

1
2
3
4
5
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <input type="submit" value="検索" />
</form>

WordPressのキーワード検索に最低限必要なHTMLです。絞り込み検索も基本はこの形で、formタグの中に絞り込み検索に必要なパーツを記述していきます。
actionにはサイトのトップページのURLを指定します。
例に挙げたコードの「bloginfo(‘url’)」で取得できるはずです。

次項から、冒頭で挙げた絞り込み検索で一般的に考えられるパーツのフォームの書き方と検索結果の表示方法を片っ端から解説していきます

キーワード検索

キーワード検索のformタグ内の記述

前の項でコード例を挙げましたがもう一度。

1
2
3
4
5
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <input type="submit" value="検索" />
</form>

注意したいのが絞り込み検索にキーワード検索が必要ない場合です。

キーワード検索が必要ない場合でも、検索結果ページを表示させるために「input type=”hidden”」で「s」を隠しパラメータとして渡してあげる必要があります。
こんな感じ。

1
2
3
4
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <input type="hidden" name="s" id="s" placeholder="検索" />
    <input type="submit" value="検索" />
</form>

要注意です。

キーワード検索の検索結果ページでの記述

検索結果ページにキーワード検索の結果を表示するコードです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
$s = $_GET['s'];
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<div>検索結果</div>
<?php
query_posts( array(
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

これは特に問題ないでしょう。

カテゴリで絞り込むチェックボックス

フォームはチェックボックスが一番厄介です笑
複数選択されることを考慮して値を配列で扱う必要があるからです。

カテゴリで絞り込むチェックボックスのformタグ内の記述

formタグ内に記述するタグはこの記事の応用です。
カテゴリ毎の記事一覧を表示する方法[WordPress]

1
2
3
4
5
6
7
8
9
10
11
12
13
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>カテゴリ</div>
<?php
$categories = get_categories();
foreach($categories as $category) :
?>
<label><input type="checkbox" name="catnum[]" value="<?php echo $category->term_id; ?>"><?php echo $category->name; ?></label><br>
<?php endforeach; ?>
    <input type="submit" value="検索" />
</form>

「name=”catnum[]”」とすることによって「cutnum」の形式が配列になります。これで複数選択されてもそれぞれ値が格納されるのでモーマンタイです。
また、このコードだとWordPressのコードでループさせて表示しているので途中でカテゴリが増えたとしても修正する必要がありません。

カテゴリで絞り込むチェックボックスの検索結果ページでの記述

カテゴリで絞り込むチェックボックスの結果を表示するコードです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
$s = $_GET['s'];
$catnum = $_GET['catnum'];
//tax_query用
if($catnum){
    $taxquerysp[] = array(
            'taxonomy'=>'category',
            'terms'=> $catnum,
            'include_children'=>false,
            'field'=>'term_id',
            'operator'=>'AND'
            );
}
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php
if (is_array($catnum)) { ?>カテゴリ:<?php
foreach($catnum as $val){
if ($val === end($catnum)) {
echo get_cat_name($val);
    }else{
echo get_cat_name($val).", ";
}
}
}
 ?>
<div>検索結果</div>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

カテゴリで絞り込むチェックボックス以外のパーツ(プルダウン等)

チェックボックス以外の絞り込みを見ていきましょう。
参考コードはプルダウンになりますが、ラジオボタンもHTMLコードが変わるだけで基本は一緒です。

カテゴリで絞り込むチェックボックス以外のパーツのformタグ内の記述

上で紹介したカテゴリのチェックボックスと同じくこの記事の応用です。
カテゴリ毎の記事一覧を表示する方法[WordPress]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>カテゴリ</div>
    <select name="catnum">
        <option value="" selected>カテゴリ</option>
        <?php
        $categories = get_categories();
        foreach($categories as $category) :
        ?>
            <option value="<?php echo $category->term_id; ?>"><?php echo $category->cat_name; ?></option>
        <?php endforeach; ?>
    </select>
    <input type="submit" value="検索" />
</form>

カテゴリで絞り込むチェックボックス以外のパーツの検索結果ページでの記述

配列を考えないでよいぶん検索条件として選択されたカテゴリを表示するコードは簡単です。「tax_query」用の記述はチェックボックスと変わりません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
$s = $_GET['s'];
$catnum = $_GET['catnum'];
//tax_query用
if($catnum){
    $taxquerysp[] = array(
            'taxonomy'=>'category',
            'terms'=> $catnum,
            'include_children'=>false,
            'field'=>'term_id',
            'operator'=>'AND'
            );
}
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($catnum){ ?>カテゴリ:<?php echo get_cat_name($catnum); } ?>
<div>検索結果</div>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

タグまたはカスタムタクソノミーで絞り込むチェックボックス

基本はカテゴリの絞り込みと一緒です。ただタクソノミーの情報をとってくるコードが違うだけです。

タグまたはカスタムタクソノミーで絞り込むチェックボックスのformタグ内の記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>タグまたはカスタムタクソノミー</div>
<?php
$taxonomy_name = 'post_tag';
$taxonomys = get_terms($taxonomy_name);
if(!is_wp_error($taxonomys) && count($taxonomys)):
    foreach($taxonomys as $taxonomy):
        $tax_posts = get_posts(array('post_type' => get_post_type(), 'taxonomy' => $taxonomy_name, 'term' => $taxonomy->slug ) );
        if($tax_posts):
?>
<label><input type="checkbox" name="post_tag[]" value="<?php echo $taxonomy->slug; ?>"><?php echo $taxonomy->name; ?></label><br>
<?php
        endif;
    endforeach;
endif;
?>
    <input type="submit" value="検索" />
</form>

この例はタグのチェックボックスになりますがカスタムタクソノミーの場合は7行目の「$taxonomy_name = ‘post_tag’;」の値をタクソノミー名に変更するだけです。

「name=”post_tag[]”」とすることによって「post_tag」の形式が配列になります。これで複数選択されてもそれぞれ値が格納されるのでモーマンタイです。
また、このコードだとWordPressのコードでループさせて表示しているので途中でタグやカスタムタクソノミーが増えたとしても修正する必要がありません。

因みに、「投稿」ではなく「カスタム投稿タイプ」で絞り込み検索を考えているのであれば、11行目の「’post_type’ => get_post_type()」の値をカスタム投稿タイプ名に変更する必要がでてきます。

上のコードで、うまくタグかタクソノミーの一覧をとってこれない時は、このコードの前に

1
<?php wp_reset_query(); ?>

を記述してqueryをリセットしてみてください。

タグまたはカスタムタクソノミーで絞り込むチェックボックスの検索結果ページでの記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
$s = $_GET['s'];
$post_tag = $_GET['post_tag'];
//tax_query用
if($post_tag){
    $taxquerysp[] = array(
            'taxonomy'=>'post_tag',
            'terms'=> $post_tag,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php
if (is_array($post_tag)) { ?>タグ(カスタムタクソノミー):<?php
foreach($post_tag as $val){
if ($val === end($post_tag)) {
echo get_term_by('slug',$val,"post_tag")->name;
    }else{
echo get_term_by('slug',$val,"post_tag")->name.", ";
}
}
}
 ?>
<div>検索結果</div>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

上のコードはタグでの絞り込みを想定しているので「’taxonomy’=>’post_tag’」や「echo get_term_by(‘slug’,$val,”post_tag”)->name;」で「post_tag」を指定していますが、カスタムタクソノミーの場合はタクソノミー名を入れてくださいね。

タグまたはカスタムタクソノミーで絞り込むチェックボックス以外のパーツ(プルダウン等)

これも基本はカテゴリのチェックボックス以外とおんなじことです。

タグまたはカスタムタクソノミーで絞り込むチェックボックス以外のパーツのformタグ内の記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>カテゴリ</div>
    <select name="catnum">
    <?php
    $taxonomy_name = 'post_tag';
    $taxonomys = get_terms($taxonomy_name);
    if(!is_wp_error($taxonomys) && count($taxonomys)):
        foreach($taxonomys as $taxonomy):
            $tax_posts = get_posts(array('post_type' => get_post_type(), 'taxonomy' => $taxonomy_name, 'term' => $taxonomy->slug ) );
            if($tax_posts):
    ?>
    <option value="<?php echo $taxonomy->slug; ?>"><?php echo $taxonomy->name; ?></option>
    <?php
            endif;
        endforeach;
    endif;
    ?>
    </select>
    <input type="submit" value="検索" />
</form>

注意するべきことはタグのチェックボックスの時と一緒です。

この例はタグのチェックボックスになりますがカスタムタクソノミーの場合は7行目の「$taxonomy_name = ‘post_tag’;」の値をタクソノミー名に変更するだけです。

「投稿」ではなく「カスタム投稿タイプ」で絞り込み検索を考えているのであれば、11行目の「’post_type’ => get_post_type()」の値をカスタム投稿タイプ名に変更する必要がでてきます。

上のコードで、うまくタグかタクソノミーの一覧をとってこれない時は、このコードの前に

1
<?php wp_reset_query(); ?>

を記述してqueryをリセットしてみてください。

タグまたはカスタムタクソノミーで絞り込むチェックボックス以外のパーツの検索結果ページでの記述

配列を考えないで良い分、検索条件として選択されたタグまたはカスタムタクソノミーを表示するコードは簡単です。「tax_query」用の記述はチェックボックスと変わりません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
$s = $_GET['s'];
$post_tag = $_GET['post_tag'];
//tax_query用
if($post_tag){
    $taxquerysp[] = array(
            'taxonomy'=>'post_tag',
            'terms'=> $post_tag,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($post_tag){ ?>タグ(カスタムタクソノミー):<?php echo get_term_by('slug',$post_tag,"post_tag")->name; } ?>
<div>検索結果</div>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

チェックボックスの項目にも書いたのですが、一応。上のコードはタグでの絞り込みを想定しているので「’taxonomy’=>’post_tag’」や「echo get_term_by(‘slug’,$val,”post_tag”)->name;」で「post_tag」を指定していますが、カスタムタクソノミーの場合はタクソノミー名を入れてくださいね。

カスタムフィールドで絞り込むチェックボックス

カスタムフィールドの値で絞り込む方法を見ていきましょう。まずはチェックボックスです。

カスタムフィールドで絞り込むチェックボックスのformタグ内の記述

1
2
3
4
5
6
7
8
9
10
11
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>カスタムフィールド</div>
    <label><input type="checkbox" name="kodawari[]" value="駐車場あり">駐車場あり</label><br>
    <label><input type="checkbox" name="kodawari[]" value="バス・トイレ別">バス・トイレ別</label><br>
    <label><input type="checkbox" name="kodawari[]" value="ペット相談">ペット相談</label><br>
    <label><input type="checkbox" name="kodawari[]" value="2階以上住戸">2階以上住戸</label>
    <input type="submit" value="検索" />
</form>

KoToRiの知る限りカスタムフィールドの選択肢を取ってくるコードは無いので直で書く必要があります。
「直で書く」ということは増えたり減ったりした場合に修正が必要になるということです。
これが絞り込み検索にカスタムフィールドを利用する際の欠点ですね。

カスタムフィールドで絞り込むチェックボックスの検索結果ページでの記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
$s = $_GET['s'];
$kodawari = $_GET['kodawari'];
//meta_query用
if($kodawari){
    foreach($kodawari as $val){
        $metaquerysp[] = array(
                'key'=>'kodawari',
                'value'=> $val,
                );
    }
}
$metaquerysp['relation'] = 'AND';
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if (is_array($kodawari)) { ?>カスタムフィールド:<?php
if (is_array($kodawari)) {
foreach($kodawari  as $val){
if ($val === end($kodawari)) {
echo $val;
    }else{
echo $val.", ";
}
}
}
}
 ?>
<div>検索結果</div>
<?php
query_posts( array(
    'meta_query' => $metaquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

カスタムフィールドで絞り込む場合は「meta_query」を使用します!
「meta_query」の場合、「tax_query」と違い「value」に配列を入れると正常に機能しないのです。
なので値の数だけforeachで条件を増やしています。

また、「tax_query」「meta_query」ともに条件が複数になる場合は「relation」を指定する必要があります。
今回は絞り込み検索なので「AND(すべての条件に一致)」を指定しています。

カスタムフィールドで絞り込むチェックボックス以外のパーツ

次はカスタムフィールドのチェックボックス以外のパーツです。

カスタムフィールドで絞り込むチェックボックス以外のパーツのformタグ内の記述

1
2
3
4
5
6
7
8
9
10
11
12
13
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>カスタムフィールド</div>
    <select name="type">
        <option value="" selected>ルームタイプ</option>
        <option value="アパート">アパート</option>
        <option value="マンション">マンション</option>
        <option value="一戸建て・その他">一戸建て・その他</option>
    </select>
    <input type="submit" value="検索" />
</form>

これもカスタムフィールドの選択肢を取ってくるコードは無いので直で書く必要があります。
「直で書く」ということは増えたり減ったりした場合に修正が必要になるということです。
これが絞り込み検索にカスタムフィールドを利用する際の欠点ですね。

カスタムフィールドで絞り込むチェックボックス以外のパーツの検索結果ページでの記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
$s = $_GET['s'];
$type = $_GET['type'];
//meta_query用
if($type){
    $metaquerysp[] = array(
            'key'=>'type',
            'value'=> $type,
            );
}
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($type){ ?>カスタムフィールド:<?php echo $type; } ?>
<div>検索結果</div>
<?php
query_posts( array(
    'meta_query' => $metaquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

特に難しいところはありませんね。

カスタムフィールドの値で数値比較

サンプル(ベーシック認証:ユーザ名 admin / パスワード kotori)でいうところの家賃のフィールドですね。
これ一見難しそうですが実は楽勝です。
サンプルと同じく家賃を想定して解説していきます。

家賃のカスタムフィールドを作成する

絞り込み検索を行うため家賃のカスタムフィールドを作成します。
そこに入力された数値を判定して絞り込み検索させます。

カスタムフィールドの値で数値比較するためのformタグ内の記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
    <label for="s" class="assistive-text">検索</label>
    <input type="text" name="s" id="s" placeholder="検索" />
    <div>家賃(カスタムフィールドのテキストフィールド)</div>
    <select name="low">
        <option value="0" selected>下限なし</option>
        <option value="20000">20,000円以上</option>
        <option value="25000">25,000円以上</option>
        <option value="30000">30,000円以上</option>
        <option value="35000">35,000円以上</option>
        <option value="40000">40,000円以上</option>
        <option value="45000">45,000円以上</option>
        <option value="50000">50,000円以上</option>
        <option value="55000">55,000円以上</option>
        <option value="60000">60,000円以上</option>
        <option value="65000">65,000円以上</option>
        <option value="70000">70,000円以上</option>
        <option value="75000">75,000円以上</option>
        <option value="80000">80,000円以上</option>
    </select> ~<br />
    <select name="high">
        <option value="20000">20,000円以下</option>
        <option value="25000">25,000円以下</option>
        <option value="30000">30,000円以下</option>
        <option value="35000">35,000円以下</option>
        <option value="40000">40,000円以下</option>
        <option value="45000">45,000円以下</option>
        <option value="50000">50,000円以下</option>
        <option value="55000">55,000円以下</option>
        <option value="60000">60,000円以下</option>
        <option value="65000">65,000円以下</option>
        <option value="70000">70,000円以下</option>
        <option value="75000">75,000円以下</option>
        <option value="80000">80,000円以下</option>
        <option value="9999999" selected>上限なし</option>
    </select>
    <input type="submit" value="検索" />
</form>

数値の区切りは各々変更してください。

カスタムフィールドの値で数値比較するための検索結果ページの記述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
$s = $_GET['s'];
$low = $_GET['low'];
$high = $_GET['high'];
//meta_query用
$metaquerysp[] = array(
            'key'=>'price',
            'value'=>array( $low, $high ),
            'compare'=>'BETWEEN',
            'type'=>'NUMERIC',
            );
?>
<div>検索条件</div>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($low == 0 && $high == 9999999){}else{ ?>家賃:<?php if($low == 0){ ?>下限なし<?php }else{ echo number_format($low).'円'; } ?> ~ <?php if($high == 9999999){ ?>上限なし<?php }else{ echo number_format($high).'円';} ?><?php } ?>
<div>検索結果</div>
<?php
query_posts( array(
    'meta_query' => $metaquerysp,
    's' => $s,
    )
);
?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
<?php endwhile; else : ?>
<div>該当なし</div>
<?php endif;
wp_reset_query(); ?>

ここでのミソはなんといっても「meta_query」用のコードでしょう。
「value」に取得した二つの数値を格納し「type」で「NUMERIC」を指定することにより「value」の値を数値として扱うことができます。
あとは「compare」の指定によってさまざまな条件で絞り込むことが可能です。今回は「BETWEEN」を指定しています。
「BETWEEN」を指定すると、カスタムフィールド「price」が「value」に指定した2つの数値の間の場合にヒットします。

複数の条件を組み合わせる

前の項までは条件が一つ(キーワード検索を除く)の場合のコードでしたが、それぞれを組み合わせることにより不動産サイトのような絞り込み検索を実現できるというわけです。

この項ではKoToRiの絞り込み検索サンプル(ベーシック認証:ユーザ名 admin / パスワード kotori)のコードを公開しようと思います。
一番手っ取り早くて分かりやすいですよね。

■フォーム

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<form method="get" id="searchform" action="<a href="http://kotori-blog.com/test/">http://kotori-blog.com/test/</a>">
<label for="s" class="assistive-text">検索</label>
<input type="text" class="field" name="s" id="s" placeholder="検索" />
<select name="catnum" style="margin-top:20px;">
    <option value="" selected>カテゴリ</option>
                                    <?php
$categories = get_categories('parent=0');
foreach($categories as $category) :
?>
    <option value="<?php echo $category->term_id; ?>"><?php echo $category->cat_name; ?></option>
<?php endforeach; ?>
</select>
<select name="placenum" style="margin-top:20px;">
    <option value="" selected>間取りタイプ(カスタムタクソノミー)</option>
<?php
$taxonomy_name = 'place';
$taxonomys = get_terms($taxonomy_name);
if(!is_wp_error($taxonomys) && count($taxonomys)):
    foreach($taxonomys as $taxonomy):
        $tax_posts = get_posts(array('post_type' => get_post_type(), 'taxonomy' => $taxonomy_name, 'term' => $taxonomy->slug ) );
        if($tax_posts):
?>
<option value="<?php echo $taxonomy->slug; ?>"><?php echo $taxonomy->name; ?></option>
<?php
        endif;
    endforeach;
endif;
?>
</select>
<select name="type" style="margin-top:20px;">
    <option value="" selected>ルームタイプ(カスタムフィールドのセレクトボックス)</option>
    <option value="アパート">アパート</option>
    <option value="マンション">マンション</option>
    <option value="一戸建て・その他">一戸建て・その他</option>
</select>
<div style="margin-top:20px">家賃(カスタムフィールドのテキストフィールド)</div>
<select name="low" style="margin-top:5x;">
    <option value="0" selected>下限なし</option>
    <option value="20000">20,000円以上</option>
    <option value="25000">25,000円以上</option>
    <option value="30000">30,000円以上</option>
    <option value="35000">35,000円以上</option>
    <option value="40000">40,000円以上</option>
    <option value="45000">45,000円以上</option>
    <option value="50000">50,000円以上</option>
    <option value="55000">55,000円以上</option>
    <option value="60000">60,000円以上</option>
    <option value="65000">65,000円以上</option>
    <option value="70000">70,000円以上</option>
    <option value="75000">75,000円以上</option>
    <option value="80000">80,000円以上</option>
</select> ~<br />
<select name="high" style="margin-top:5px;">
    <option value="20000">20,000円以下</option>
    <option value="25000">25,000円以下</option>
    <option value="30000">30,000円以下</option>
    <option value="35000">35,000円以下</option>
    <option value="40000">40,000円以下</option>
    <option value="45000">45,000円以下</option>
    <option value="50000">50,000円以下</option>
    <option value="55000">55,000円以下</option>
    <option value="60000">60,000円以下</option>
    <option value="65000">65,000円以下</option>
    <option value="70000">70,000円以下</option>
    <option value="75000">75,000円以下</option>
    <option value="80000">80,000円以下</option>
    <option value="9999999" selected>上限なし</option>
</select>
<div style="margin-top:20px">こだわり(タグ)</div>
<?php
$taxonomy_name = 'post_tag';
$taxonomys = get_terms($taxonomy_name);
if(!is_wp_error($taxonomys) && count($taxonomys)):
    foreach($taxonomys as $taxonomy):
        $tax_posts = get_posts(array('post_type' => get_post_type(), 'taxonomy' => $taxonomy_name, 'term' => $taxonomy->slug ) );
        if($tax_posts):
?>
<label><input type="checkbox" name="post_tag[]" value="<?php echo $taxonomy->slug; ?>"><?php echo $taxonomy->name; ?></label><br>
<?php
        endif;
    endforeach;
endif;
?>
<div>こだわり(カスタムフィールドのチェックボックス)</div>
<label><input type="checkbox" name="kodawari[]" value="駐車場あり">駐車場あり</label><br>
<label><input type="checkbox" name="kodawari[]" value="バス・トイレ別">バス・トイレ別</label><br>
<label><input type="checkbox" name="kodawari[]" value="ペット相談">ペット相談</label><br>
<label><input type="checkbox" name="kodawari[]" value="2階以上住戸">2階以上住戸</label>
<input type="submit" class="submit" name="submit" id="searchsubmit" value="検索" />
</form>

■検索結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
$s = $_GET['s'];
$catnum = $_GET['catnum'];
$placenum = $_GET['placenum'];
$type = $_GET['type'];
$low = $_GET['low'];
$high = $_GET['high'];
$post_tag = $_GET['post_tag'];
$kodawari = $_GET['kodawari'];
if($catnum){
    $taxquerysp[] = array(
            'taxonomy'=>'category',
            'terms'=> $catnum,
            'include_children'=>false,
            'field'=>'term_id',
            'operator'=>'AND'
            );
}
if($post_tag){
    $taxquerysp[] = array(
            'taxonomy'=>'post_tag',
            'terms'=> $post_tag,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
if($placenum){
    $taxquerysp[] = array(
            'taxonomy'=>'place',
            'terms'=> $placenum,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
$taxquerysp['relation'] = 'AND';
if($kodawari){
    foreach($kodawari as $val){
        $metaquerysp[] = array(
                'key'=>'kodawari',
                'value'=> $val,
                );
    }
}
if($type){
    $metaquerysp[] = array(
            'key'=>'type',
            'value'=> $type,
            'compare'=>'=',
            );
}
$metaquerysp[] = array(
            'key'=>'price',
            'value'=>array( $low, $high ),
            'compare'=>'BETWEEN',
            'type'=>'NUMERIC',
            );
$metaquerysp['relation'] = 'AND';
?>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($catnum){ ?>カテゴリ:<?php echo get_cat_name($catnum); ?><br><?php } ?>
<?php if($placenum){ ?>間取りタイプ:<?php echo get_term_by('slug',$placenum,"place")->name; ?><br><?php } ?>
<?php if($type){ ?>ルームタイプ:<?php echo $type; ?><br><?php } ?>
<?php if($low == 0 && $high == 9999999){}else{ ?>家賃:<?php if($low == 0){ ?>下限なし<?php }else{ echo number_format($low).'円'; } ?> ~ <?php if($high == 9999999){ ?>上限なし<?php }else{ echo number_format($high).'円';} ?><br>
<br><?php } ?>
<?php
if (is_array($cutnum)) { ?>カテゴリ:<?php
foreach($cutnum as $val){
if ($val === end($cutnum)) {
echo get_cat_name($catnum);
    }else{
echo get_cat_name($catnum).", ";
}
}
}
 ?>
<?php
if (is_array($post_tag)) { ?>こだわり(タグ):<?php
foreach($post_tag as $val){
if ($val === end($post_tag)) {
echo get_term_by('slug',$val,"post_tag")->name;
    }else{
echo get_term_by('slug',$val,"post_tag")->name.", ";
}
}
 ?><br><br><?php } ?>
<?php if (is_array($kodawari)) { ?>こだわり(カスタムフィールドのチェックボックス):<?php
if (is_array($kodawari)) {
foreach($kodawari  as $val){
if ($val === end($kodawari)) {
echo $val;
    }else{
echo $val.", ";
}
}
}
}
 ?>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    'meta_query' => $metaquerysp,
    's' => $s,
    )
);
?>
            <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
            <?php endwhile; else : ?>
該当なし
            <?php endif;wp_reset_query(); ?>

「百聞は一見に如かず」です。

絞り込み検索は「tax_query」と「meta_query」で出来てます

「tax_query」と「meta_query」さえ押さえれば楽勝です。指定の仕方によっては様々なパターンの絞り込み検索が可能ですので知らなかった人は要チェックです。

tax_query

meta_query

検索結果ページでのページネーション

これは質問出そうなので押さえておきましょう。
KoToRiはページネーションは「WP-PageNavi」プラグインで実装します。
だって楽なんだもん!

「WP-PageNavi」の使い方は下記記事を参考にしてください。
ページネーションを実装できる「WP-PageNavi」[WordPress]

「WP-PageNavi」でページネーションを付けた場合の検索結果ページのコードはこの様になります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?php
$s = $_GET['s'];
$catnum = $_GET['catnum'];
$placenum = $_GET['placenum'];
$type = $_GET['type'];
$low = $_GET['low'];
$high = $_GET['high'];
$post_tag = $_GET['post_tag'];
$kodawari = $_GET['kodawari'];
if($catnum){
    $taxquerysp[] = array(
            'taxonomy'=>'category',
            'terms'=> $catnum,
            'include_children'=>false,
            'field'=>'term_id',
            'operator'=>'AND'
            );
}
if($post_tag){
    $taxquerysp[] = array(
            'taxonomy'=>'post_tag',
            'terms'=> $post_tag,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
if($placenum){
    $taxquerysp[] = array(
            'taxonomy'=>'place',
            'terms'=> $placenum,
            'include_children'=>false,
            'field'=>'slug',
            'operator'=>'AND'
            );
}
$taxquerysp['relation'] = 'AND';
if($kodawari){
    foreach($kodawari as $val){
        $metaquerysp[] = array(
                'key'=>'kodawari',
                'value'=> $val,
                );
    }
}
if($type){
    $metaquerysp[] = array(
            'key'=>'type',
            'value'=> $type,
            'compare'=>'=',
            );
}
$metaquerysp[] = array(
            'key'=>'price',
            'value'=>array( $low, $high ),
            'compare'=>'BETWEEN',
            'type'=>'NUMERIC',
            );
$metaquerysp['relation'] = 'AND';
?>
<?php if($s){ ?>検索キーワード:<?php echo $s; ?><br><?php } ?>
<?php if($catnum){ ?>カテゴリ:<?php echo get_cat_name($catnum); ?><br><?php } ?>
<?php if($placenum){ ?>間取りタイプ:<?php echo get_term_by('slug',$placenum,"place")->name; ?><br><?php } ?>
<?php if($type){ ?>ルームタイプ:<?php echo $type; ?><br><?php } ?>
<?php if($low == 0 && $high == 9999999){}else{ ?>家賃:<?php if($low == 0){ ?>下限なし<?php }else{ echo number_format($low).'円'; } ?> ~ <?php if($high == 9999999){ ?>上限なし<?php }else{ echo number_format($high).'円';} ?><br>
<br><?php } ?>
<?php
if (is_array($cutnum)) { ?>カテゴリ:<?php
foreach($cutnum as $val){
if ($val === end($cutnum)) {
echo get_cat_name($catnum);
    }else{
echo get_cat_name($catnum).", ";
}
}
}
 ?>
<?php
if (is_array($post_tag)) { ?>こだわり(タグ):<?php
foreach($post_tag as $val){
if ($val === end($post_tag)) {
echo get_term_by('slug',$val,"post_tag")->name;
    }else{
echo get_term_by('slug',$val,"post_tag")->name.", ";
}
}
 ?><br><br><?php } ?>
<?php if (is_array($kodawari)) { ?>こだわり(カスタムフィールドのチェックボックス):<?php
if (is_array($kodawari)) {
foreach($kodawari  as $val){
if ($val === end($kodawari)) {
echo $val;
    }else{
echo $val.", ";
}
}
}
}
 ?>
<?php
query_posts( array(
    'tax_query' => $taxquerysp,
    'meta_query' => $metaquerysp,
    's' => $s,
    'posts_per_page' => 1,
    'paged' => $paged,
    )
);
?>
            <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div><?php the_title(); ?></div>
<div><?php the_content(); ?></div>
            <?php endwhile; else : ?>
該当なし
            <?php endif; ?>
<?php
wp_pagenavi(); //ページ送り
wp_reset_query();
 ?>

もし2ページ目以降が404エラーになるようでしたら管理画面「設定」→「表示設定」から「1ページに表示する最大投稿数」を「1」に指定すると直るかもしれません。

まとめ

くぅ~疲れました!
思いのほか超大作になってしまいましたね。

大分長いですが、これを読めば絞り込み検索を割とスムーズに実装できるのではないでしょうか。

でも実際に不動産サイトで絞り込み検索が必要なら「不動産プラグイン」使っちゃえばもっと簡単だと思います。
KoToRiは未だ使ったこと無いのですが!

何度も言いますがミソは「tax_query」と「meta_query」です。
今回紹介したのは本当にANDの絞り込み検索に的を絞ったコードですが、指定の仕方によって変化自在です。
ベーシックなコードの書き方はこの記事を参考にしてもらって色々応用を利かせていってもらえればと思いますよ!

チャオ!

标签TAGS

与标签相关的文章

最新文章

热门文章

其他文章

Sign up for our Newsletter

iPhone

Lorem ipsum dolor sit amet

MacBook

Sed do eiusmod tempor incididunt

iPad

Tempor incididunt ut labore et dolore