カスタムフィールド値で絞り込み検索をする方法7種類
本記事では、カスタム投稿タイプにおける、カスタムフィールド値での絞り込み検索について解説していきたいと思います。
カスタム投稿タイプにおける絞り込み検索(土台編)で作成したファイルを元にカスタマイズしていきますので、土台編がまだの方は先にそちらを読んでからの方が分かりやすいかと思います。
カスタムフィールドは、プラグイン「Advanced Custom Fields」で作成しています。
共通の設定
これからカスタムフィールド値での絞り込み検索について何種類か見ていきますが、記述は共通になる部分も多いので、先に共通の部分を解説しておきます。
どの絞り込みも、土台編で作った検索フォーム(searchform.php)、検索結果ページ(search-products.php)、それとfunctions.phpを編集していきます。
searchform.php
「ここに追加の検索項目を書く」とコメントがあるところにそれぞれの項目を追加していきます。
共通の設定はありません。
search-products.php
土台編で「ここに追加の条件を書く」とコメントがあるところに、条件を追加していきます。
カスタムフィールドの絞り込みが1種類だけの場合、$argsの中に以下のように追記していきます。
$args = array(
'post_type' => 'products', // 投稿タイプ
・・・
// カスタムフィールド値での絞り込み
'meta_key' => '〇〇',
'meta_value' => '〇〇',
'meta_compare' => '〇〇',
);もし2種類以上のカスタムフィールド値で絞り込む場合は、以下のように配列にし、それぞれの絞り込み条件の関係性を示す必要があります。
$args = array(
'post_type' => 'products', // 投稿タイプ
・・・
// カスタムフィールド値での絞り込み
'meta_query' => array(
// 絞り込み条件の関係
'relation' => 'AND', // またはOR
// 絞り込み条件その1
array(
'key' => '〇〇',
'value' => '〇〇',
'compare' => '〇〇',
),
// 絞り込み条件その2
array(
'key' => '〇〇',
'value' => '〇〇',
'compare' => '〇〇',
),
),
);functions.php
送信されたデータを取得するにはget_query_var()を使いますが、独自のGETパラメータを使う場合はfunctions.phpで許可が必要なので以下を記述します。
function add_query_vars_filter( $vars ){
$vars[] = '〇〇';
$vars[] = '〇〇';
・・・
return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );セレクトボックス編
例えば服のサイズに関する項目をカスタムフィールドを作るとしましょう。
商品一覧から、希望するサイズ展開がある服を絞り込めるようにします。
カスタムフィールドの設定内容
管理画面では複数のサイズを登録できるように、フィールドタイプはチェックボックスにしています。
- フィールドラベル:サイズ展開
- フィールド名:size
- フィールドタイプ:チェックボックス
- 選択肢:small : Sサイズ / medium : Mサイズ / large : Lサイズ
searchform.php
<select name="size-select">
<option value="">▼すべてのサイズ</option>
<option value="small" <?php echo get_query_var('size-select') === 'small' ? 'selected' : ''; ?>>Sサイズ</option>
<option value="medium" <?php echo get_query_var('size-select') === 'medium' ? 'selected' : ''; ?>>Mサイズ</option>
<option value="large" <?php echo get_query_var('size-select') === 'large' ? 'selected' : ''; ?>>Lサイズ</option>
</select>選択肢<option>のvalue値はカスタムフィールドの選択肢と一致させます。
そして<?php echo get_query_var(‘size-select’) === ‘〇〇’ ? ‘selected’ : ”; ?>で、「選択サイズが〇〇のときselectedを出力、そうでなければ何も表示しない」とし、検索後も選択サイズを保持するようにしています。
「すべてのサイズ」はサイズ選択をしないという意味で、全サイズの商品が対象になります。項目が不要であれば消してください。
search-products.php
絞り込みの条件として、以下を追記します。
条件が複数になる場合は、「共通の設定」で解説した書き方に変えてください。
'meta_key' => 'size',
'meta_value' => get_query_var('size-select'),
'meta_compare' => 'LIKE',比較方法meta_compareをLIKEにすると、例えば「Mサイズ / Lサイズ」の2サイズ展開商品があった場合、「Mサイズ」を選択しても「Lサイズ」を選択しても検索に引っかかります。
functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'size-select'; // サイズ選択ラジオボタン編
例えば商品の状態に関する項目をカスタムフィールドで作るとしましょう。
商品一覧から、希望する状態の商品を絞り込めるようにします。
カスタムフィールドの設定内容
管理画面ではどちらか一方の状態を選択できるように、ラジオボタンにしています。
- フィールドラベル:ステータス
- フィールド名:status
- フィールドタイプ:ラジオボタン
- 選択肢:new : 新品 / old : 中古
searchform.php
<label><input type="radio" name="status-select" value="new" <?php echo get_query_var('status-select') === 'new' ? 'checked' : ''; ?>>新品</label>
<label><input type="radio" name="status-select" value="old" <?php echo get_query_var('status-select') === 'old' ? 'checked' : ''; ?>>中古</label>
<label><input type="radio" name="status-select" value="" <?php echo get_query_var('status-select') === '' ? 'checked' : ''; ?>>選択しない</label>カスタムフィールドの選択肢とvalue値は一致させます。
そして<?php echo get_query_var(‘status-select’) === ‘〇〇’ ? ‘checked’ : ”; ?>で、「選択ステータスが〇〇のときcheckedを出力、そうでなければ何も表示しない」とし、検索後も選択サイズを保持するようにしています。
最初は「選択しない」にチェックが入った状態で、全ステータスの商品が対象になります。
search-products.php
絞り込みの条件として、以下を追記します。
条件が複数になる場合は、「共通の設定」で解説した書き方に変えてください。
'meta_key' => 'status',
'meta_value' => get_query_var('status-select'),
'meta_compare' => 'LIKE',管理画面でのフィールドタイプをラジオボタンにしている(1商品に対し1つのステータスしか登録できない)ので、LIKEの部分をINや=に変えても同じような検索結果になります。
ただしINや=にすると、「選択しない」を選択された場合の結果が出なくなるのでご注意ください。
functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'status-select'; // ステータス選択数値編
例えば商品の価格に関する項目をカスタムフィールドで作るとしましょう。
商品一覧から、希望する価格帯の商品を絞り込めるようにします。
カスタムフィールドの設定内容
価格は数値で絞り込むので、フィールドタイプは「数値」にしています。
- フィールドラベル:価格
- フィールド名:price
- フィールドタイプ:数値
searchform.php
<span>価格帯</span>
<input type="number" name="price-low" value="<?php echo get_query_var( 'price-low' ) ? esc_attr(get_query_var( 'price-low' )) : ''; ?>">
<span>~</span>
<input type="number" name="price-high" value="<?php echo get_query_var( 'price-high' ) ? esc_attr(get_query_var( 'price-high' )) : ''; ?>">
<span>円</span>少し長くなっていますが、<?php echo get_query_var(‘〇〇’) ? esc_attr(get_query_var( ‘〇〇’ )) : ”; ?>で「〇〇の値があればその値を出力、値がなければ何も表示しない」としています。
これで検索後も入力した数値が検索欄に保持されるはずです。
気を付けたいのが、value=”<?php ~ ?>”の「value=”」と「<?php」の間、「?>」と「”」の間にはスペースを入れないことです。
検索自体は問題なく行われますが、入力した数値が保持されず消えてしまいます。
私はしばらくこのスペースに気付けずに苦労しました。
search-products.php
あらかじめ、$argsの外側で最低価格・最高価格を定義しておきます。
// 最低価格
$price_low = get_query_var('price-low');
// 最高価格
if(get_query_var('price-high')) {
$price_high = get_query_var('price-high');
} else {
$price_high = 99999999999;
}最低価格はname=”price-low”に入力された数値を取得し、変数$price_lowに入れています。
数値が入力されなかった場合は、おそらく0が入っていると思われます。
最高価格は、数値が入力されなかった場合に「最大値=0」となると困るので、name=”price-high”に入力された数値があればその値を変数$price_highに入れ、なければ適当な高額金額が入るようにしておきます。
そして絞り込みの条件として、$args内に以下を追記します。
条件が複数になる場合は、「共通の設定」で解説した書き方に変えてください。
'meta_key' => 'price',
'meta_value' => array($price_low, $price_high),
'meta_type' => 'NUMERIC',
'meta_compare' => 'BETWEEN',最低価格と最高価格は配列にして、meta_valueに指定します。
フィールドタイプの型は数値なのでmeta_typeはNUMERICを指定。
そしてmeta_compareをBETWEENにすることで、priceの値が$price_low~$price_highである商品を出力できます。
functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'price-low'; // 最低価格
$vars[] = 'price-high'; // 最高価格スピンボタンを消す方法
入力をtype=”number”にすると数値の入力欄横に上下の矢印が表示されることがあります。
これはスピンボタンと言って、この矢印の操作で数値を入力したり変更したりするものですが、気になるようならCSSで非表示にすることもできます。
/* Chrome、Safari */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* FireFox、IE */
input[type="number"] {
-moz-appearance: textfield;
} チェックボックス編
例えば商品の色に関する項目をカスタムフィールドで作るとしましょう。
商品一覧から、希望する色の商品を絞り込めるようにします。
カスタムフィールドの設定内容
管理画面で複数のカラーを登録するとうまく検索できなかったので、1つの商品に対して1つのカラー登録となるように、フィールドタイプはラジオボタンにしています。
- フィールドラベル:カラー
- フィールド名:color
- フィールドタイプ:ラジオボタン
- 選択肢:red : 赤 / white : 白 / black : 黒
searchform.php
<label><input type="checkbox" name="color1" value="red" <?php echo get_query_var('color1') ? 'checked' : ''; ?>>赤</label>
<label><input type="checkbox" name="color2" value="white" <?php echo get_query_var('color2') ? 'checked' : ''; ?>>白</label>
<label><input type="checkbox" name="color3" value="black" <?php echo get_query_var('color3') ? 'checked' : ''; ?>>黒</label>ラジオボタンと同じように<?php echo get_query_var(‘〇〇’) === ‘〇〇’ ? ‘checked’ : ”; ?>で、「〇〇がチェックされているときcheckedを出力、そうでなければ何も表示しない」とし、検索後も選択チェックを保持するようにしています。
ただし気を付けたいのは、検索前はチェックが入らずそのまま検索すると検索結果が出てこないことです。
例えば、カラーは選択をせずに他の検索項目で絞り込みをしようとした場合に、意図しない結果になる可能性があります。
検索結果ページではチェックを入れた項目を引き継ぎ、それ以外のページ(最初の検索画面など)では全てにチェックを入れておく、というように条件分岐で書くといいかもしれません。
<?php if ( is_search() ) : ?>
<label><input type="checkbox" name="color1" value="red" <?php echo get_query_var('color1') ? 'checked' : ''; ?>>赤</label>
<label><input type="checkbox" name="color2" value="white" <?php echo get_query_var('color2') ? 'checked' : ''; ?>>白</label>
<label><input type="checkbox" name="color3" value="black" <?php echo get_query_var('color3') ? 'checked' : ''; ?>>黒</label>
<?php else : ?>
<label><input type="checkbox" name="color1" value="red" checked>赤</label>
<label><input type="checkbox" name="color2" value="white" checked>白</label>
<label><input type="checkbox" name="color3" value="black" checked>黒</label>
<?php endif; ?>こうすれば、わざわざチェックを外さない限りは、全カラー対象での検索をすることができます。
search-products.php
あらかじめ、$argsの外側で選択されたカラーを定義しておきます。
$checked_color = array();
for ( $i = 1; $i <= 3; $i++ ) {
$checked_color[] = get_query_var( 'color' . $i );
}これで選択されたカラーの値が$checked_colorに配列として入ります。
そして絞り込みの条件として、$args内に以下を追記します。
条件が複数になる場合は、「共通の設定」で解説した書き方に変えてください。
'meta_key' => 'color',
'meta_value' => $checked_color,
'meta_compare' => 'IN',比較方法meta_compareをINにすると、例えば「赤」と「白」が選択された場合、「赤」の商品と「白」の商品が両方検索に引っかかります。
functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'color1'; // カラー選択
$vars[] = 'color2'; // カラー選択
$vars[] = 'color3'; // カラー選択真 / 偽 編
例えば商品の機能に関する項目をカスタムフィールドで作るとしましょう。
商品一覧から、希望する機能を持つ商品を絞り込めるようにします。
カスタムフィールドの設定内容
管理画面では1つの商品に対して、機能の「有・無」を登録できるように、フィールドタイプは真 / 偽にしています。
3種類の機能について、それぞれフィールドを作成しました。
- フィールドラベル:アラート機能
- フィールド名:alert
- フィールドタイプ:真 / 偽
- フィールドラベル:人感センサー
- フィールド名:sensor
- フィールドタイプ:真 / 偽
- フィールドラベル:タイマー機能
- フィールド名:timer
- フィールドタイプ:真 / 偽
searchform.php
<label><input type="checkbox" name="alert-check" <?php echo get_query_var('alert-check') === 'on' ? 'checked' : ''; ?>>アラート機能付き</label>
<label><input type="checkbox" name="sensor-check" <?php echo get_query_var('sensor-check') === 'on' ? 'checked' : ''; ?>>人感センサー搭載</label>
<label><input type="checkbox" name="timer-check" <?php echo get_query_var('timer-check') === 'on' ? 'checked' : ''; ?>>タイマー機能付き</label>チェックが入っている時は「name値 =on」というデータが送られているようです。
search-products.php
あらかじめ、$argsの外側でチェックのON / OFFを判別し、チェックがあった場合のみ条件が組み込まれるようにします。
// アラート機能
if(get_query_var('alert-check') === 'on') {
$alert_check = array(
'key' => 'alert',
'value' => 1,
'compare' => '=',
);
}
// 人感センサー
if(get_query_var('sensor-check') === 'on') {
$sensor_check = array(
'key' => 'sensor',
'value' => 1,
'compare' => '=',
);
}
// タイマー機能
if(get_query_var('timer-check') === 'on') {
$timer_check = array(
'key' => 'timer',
'value' => 1,
'compare' => '=',
);
}今回フィールドは「真 / 偽」で作成しているため、管理画面で「真(機能あり)」の方にチェックが入っていたら値は1、そうでなければ値は0となります。
なのでif文を使って、項目がチェックされている場合は「key(フィールド名)= 1」という条件の配列を変数に入れています。
そして絞り込みの条件として、$args内に以下を追記します。
'meta_query' => array(
// 絞り込み条件の関係
'relation' => 'AND',
$alert_check, // アラート機能
$sensor_check, // 人感センサー
$timer_check, // タイマー機能
),functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'alert-check'; // アラート機能
$vars[] = 'sensor-check'; // 人感センサー
$vars[] = 'timer-check'; // タイマー機能意図しない絞り込みに注意
真 / 偽では、$argsの外でvalue値の部分だけif文で判定すると意図しない絞り込みになる可能性があるので注意が必要です。
仮に、$argsの外で「チェックが入っていれば1、そうでいなければ0」というvalueに関する条件分岐だけを作り、$args内に各項目それぞれkey・value・compareを記述したとします。
このとき例えば「アラート機能」と「タイマー機能」だけがチェックされると、「アラート機能あり&人感センサーなし&タイマー機能あり」という絞り込みになってしまいます。
つまり「アラート機能あり&人感センサーあり&タイマー機能あり」の商品が結果に出てきません。
今回の例だと、おそらく検索をする人は「アラート機能」と「タイマー機能」は欲しいけど、「人感センサー」はどっちでもいい、という考えだと思います。
なので今回私は配列ごと$argsの外で定義し、チェックが入っていないものは条件に入れないようにしました。
ややこしいですが、状況によってうまく条件式を変えてみてください。
並べ替え編
セレクトボックスを使って、商品を並び替えて表示できるようにします。
カスタムフィールドの設定内容
商品に価格を設定し、その数値で並べ替えをしたいので、フィールドタイプは「数値」にしています(「数値編」の設定と同じ)。
- フィールドラベル:価格
- フィールド名:price
- フィールドタイプ:数値
searchform.php
<select name="order-select">
<option value="date-desc" <?php echo get_query_var('order-select') === 'date-desc' ? 'selected' : ''; ?>>登録が新しい順</option>
<option value="date-asc" <?php echo get_query_var('order-select') === 'date-asc' ? 'selected' : ''; ?>>登録が古い順</option>
<option value="price-asc" <?php echo get_query_var('order-select') === 'price-asc' ? 'selected' : ''; ?>>価格が安い順</option>
<option value="price-desc" <?php echo get_query_var('order-select') === 'price-desc' ? 'selected' : ''; ?>>価格が高い順</option>
</select>選択項目にはselectedを出力するようにし、検索後も選択項目を保持するようにしています。
search-products.php
あらかじめ、$argsの外で並びの基準と並べ方を定義します。
// 登録が新しい順
if(get_query_var('order-select') === 'date-desc') {
$order = 'DESC';
$orderby = 'date';
}
// 登録が古い順
if(get_query_var('order-select') === 'date-asc'){
$order = 'ASC';
$orderby = 'date';
}
// 価格が安い順
if(get_query_var('order-select') === 'price-asc'){
$order = 'ASC';
$orderby = 'meta_value_num';
$key = 'price';
}
// 価格が高い順
if(get_query_var('order-select') === 'price-desc'){
$order = 'DESC';
$orderby = 'meta_value_num';
$key = 'price';
}登録は投稿日date、価格はカスタムフィールドで設定したフィールド名priceを使っています。
昇順(ASC)は最低から最高へ、降順(DESC)は最高から最低へと並びます。
そして絞り込みの条件として、$args内に以下を追記します。
'order' => $order,
'orderby' => $orderby,
'meta_key' => $key,他の絞り込み条件と併用する場合はmeta_queryとして配列で記述します。
$args = array(
'order' => $order,
'orderby' => $orderby,
'meta_key' => $key,
・・・
// カスタムフィールド値での絞り込み
'meta_query' => array(
array(
'key' => '〇〇',
'value' => '〇〇',
'compare' => '〇〇',
),
),
);functions.php
「共通の設定」で記述したadd_query_vars_filter関数内に以下を追加します。
$vars[] = 'order-select'; // 並び順指定カテゴリ(タクソノミー)編
カスタム投稿タイプのカテゴリー(タクソノミー)で商品を絞り込みできるようにします。
searchform.php
実はWordPressにはカテゴリーリストを表示するテンプレートタグが用意されています。
<?php wp_dropdown_categories(); ?>が、このままだとデフォルト投稿タイプのカテゴリーリストが表示されてしまいますので、パラメータにいろいろ条件を追加していきます。
<?php wp_dropdown_categories(array(
'hierarchical' => 1,
'orderby' => 'NAME',
'show_option_all' => '▼すべてのカテゴリー',
'taxonomy' => 'products',
)); ?>- hierarchical:カテゴリーをフラットに表示する(0/False)か、階層形式で表示(1/True)するか。
- orderby:カテゴリーを並べる基準。ID(初期値)、NAME(名前)、SLUG(スラッグ)がある
- show_option_all:クリックすると 「すべてのカテゴリー」を選択できるテキスト。デフォルトでは、「すべてのカテゴリー」項目は表示されない。
- taxonomy:タクソノミーを指定。
他にもあるので、気になる方はWordPress Codex 日本語版をご覧ください。
search-products.php
「すべてのカテゴリ」項目がない場合
show_option_allの項目を設定していない場合。
$args = array(
'post_type' => 'products', // 投稿タイプ
・・・
// タクソノミーでの絞り込み
'tax_query' => array(
array(
'taxonomy' => '{タクソノミーのスラッグ},
'field' => 'term_id', // デフォルト
'terms' => get_query_var('cat'),
),
),
);テンプレートタグwp_dropdown_categoriesで出力されたカテゴリーリストには、デフォルトでname=”cat”、各項目にはvalue=”ID” が入っています。
そしてget_query_var(‘cat’)で、選択された項目のvalue値(ID)を取得しています。
これで「{タクソノミーのスラッグ}の中でterm_idが〇〇のターム」という指定ができます。
ちなみにfield(タクソノミータームの種類)はデフォルトでterm_idです。
「すべてのカテゴリ」項目がある場合
カテゴリーリストの呼び出しをするときに、show_option_allの項目を設定した場合、上の設定だと「すべてのカテゴリ」の結果がうまく出ませんでした。
私の設定が悪かったのかはわかりませんが、$argsの外で変数を定義してからぶち込むとうまく動いたので、一応その方法を書いておきます。
まず、$argsの外で、条件分岐を使って変数を定義します。
if(get_query_var('cat')) { // カテゴリが選択されている場合
$tax_query = array(
array(
'taxonomy' => 'products_category',
'terms' => get_query_var('cat'),
),
);
} else { // 「すべてのカテゴリ」が選択された場合
$tax_query = '';
}定義した変数$tax_queryを$argsの中に入れます。
$args = array(
'post_type' => 'products', // 投稿タイプ
・・・
// タクソノミーでの絞り込み
'tax_query' => $tax_query,
);まとめ
いかがでしたか?
商品がたくさんさるサイトでも、絞り込み検索をうまく設置すれば見たい商品が簡単に検索できるので便利です。
絞り込み方はケースバイケースなので難しいところもありますが、ぜひチャレンジしてみてください。
最後までご覧いただきありがとうございました。