カスタムフィールドも対象に。
search.phpではない
search.phpでもカスタム投稿を対象にした検索結果は出力できるけど、カスタム投稿別に絞り込み条件を作るなら項目も変わって使い回せないので今回は使わない。
なお、search.phpでやりたいときは検索部分はこんな感じになる。
<form action="<?php echo home_url(); ?>" method="get">
<input type="text" name="s" value="<?php the_search_query(); ?>" placeholder="検索ワード">
<input type="hidden" name="post_type" value="【カスタム投稿スラッグ】">
<button>検索</button>
</form>
複数の投稿タイプを指定したいならこんな感じ。
<form action="<?php echo home_url(); ?>" method="get">
<input type="text" name="s" value="<?php the_search_query(); ?>" placeholder="検索ワード">
<input type="hidden" name="post_type[]" value="【カスタム投稿スラッグ1】">
<input type="hidden" name="post_type[]" value="【カスタム投稿スラッグ2】">
<button>検索</button>
</form>
hiddenじゃなくてもいいんで、ラジオボタンなりチェックボックスなりで指定できるようにも作れる。
やりたいこと
- 特定のカテゴリーやらタグのものを指定する
- 特定のカスタムフィールドに該当の値があるものを指定する
- 指定した数値以上、以下みたいな条件で指定する
言ってみれば不動産サイトとか価格.comとかみたいなやつか。
前提というか環境というか
カスタム投稿:Custom Post Type UI
カスタムフィールド:Smart Custom Fields
ページャー:WP-PageNavi
記事一覧の基本形
普通に記事一覧を作るならこんな感じになる。
<?php
$paged = get_query_var('paged')? get_query_var('paged') : 1;
$myQuery = new WP_Query();
$param = array(
'posts_per_page' => '10',
'post_type' => '【カスタム投稿スラッグ】',
'paged' => $paged,
);
$myQuery->query($param);
?>
<?php if($myQuery->have_posts()): ?>
<?php while($myQuery->have_posts()) : $myQuery->the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php endwhile; ?>
<?php if(function_exists('wp_pagenavi')) { wp_pagenavi(array('query'=>$myQuery)); } ?>
<?php endif; ?>
archive.phpはもちろんのこと、page.phpでもいける。
当然ながら公開済みの記事が新着順で出力される。これに出力条件をつけていく。
複数対応のタクソノミー絞り込み
tax_queryで指定する。
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'タクソノミースラッグ1',
'field' => 'slug',
'terms' => array('ターム1','ターム2','ターム3'),
'operator' => 'IN',
),
array(
'taxonomy' => 'タクソノミースラッグ2',
'field' => 'slug',
'terms' => array('ターム1','ターム2','ターム3'),
'operator' => 'IN',
),
)
);
operatorが「IN」だと指定したタームのどれかが含まれてたら、という条件になる。そんな感じで色々やれるので、「relation」と「operator」は自分の都合のいいやつに適時変更。
meta_queryもtax_queryも、複数条件を仕込む場合は「relation」が必須なので絶対に忘れないこと。
カスタムフィールドの絞り込み
「該当のカスタムフィールドに指定の値が入ってたら」だとこんな感じ。
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => '【カスタムフィールド値】',
'compare' => '=',
'type' => 'CHAR',
),
),
);
同一フィールドで複数の値を指定することもできる。チェックボックス項目にいいですね。
逆に言うとタクソノミーと違ってタームは1個ずつしか指定できない。
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => '【カスタムフィールド名】',
'value' => '【カスタムフィールド値1】',
'compare' => 'LIKE',
),
array(
'key' => '【カスタムフィールド名】',
'value' => '【カスタムフィールド値2】',
'compare' => 'LIKE',
),
),
);
数値だとこんな感じ。
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => '【カスタムフィールド値】',
'compare' => '>=', //以上
'type' => 'NUMERIC',
),
),
);
数値でやっていくときにはtypeで数字を扱う宣言をしないとだめ。条件指定は一致する・しないだけでなく、以上・以下、未満とかそういうのもいける。
範囲内・範囲外って条件もできる。「◯◯以上〇〇以下」だとこう。
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => array(0,1000), //0~1000だったら
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
),
),
);
このとき、valueの並びは昇順になってないといけない。なので、範囲を入力フォームから拾う場合は順序がイカれることもあるんで、直接突っ込まずに整形するのがいいですね。
$valueArray = array(1000,0);
asort($valueArray);
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => $valueArray,
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
),
),
);
絞り込み用検索フォーム
前述の通り、絞り込みを行うのはsearch.phpじゃない。上記の条件を仕込んだ一覧ページに飛ばすことが大事。で、絞り込みの条件をちゃんと受け取れるようにしなきゃいけない。そこは一般的に使われるgetでいい。
基本形
◯◯~◯◯円だと例えばこんな。
<form action="【該当ページURL】" method="get">
<input type="text" name="max-num">
<input type="text" name="min-num">
<button>送信する</button>
</form>
受け取りと反映はこうなる。
<?php
$min_num = $_GET['min_num'];
$max_num = $_GET['max_num'];
$valueArray = array($min_num,$max_num);
asort($valueArray);
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => $valueArray,
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
),
),
);
記入がない場合の事も考えると、実際の構築には条件分岐が色々追加されることは想像に難くない。$paramに直書きしないで、meta_query内の配列を別で作って放り込む方がいい。
ターム一覧
<form action="【該当ページURL】" method="get">
<?php
$terms = get_terms('【タクソノミー名】');
foreach ( $terms as $term ):
$termName = esc_html($term->name);
?>
<label><input type="checkbox" name="terms[]" value="<?php echo $termName; ?>"><?php echo $termName; ?></label>
<?php endforeach; ?>
<button>送信する</button>
</form>
nameに[]を付けてるからそのまま配列として引っ張れるような。
$terms = $_GET['terms[]'];
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'tax_query' => array(
array(
'taxonomy' => 'タクソノミースラッグ',
'field' => 'slug',
'terms' => $terms,
'operator' => 'IN',
),
)
);
カスタムフィールド
カスタムフィールドの内容を絞り込みに使いたい場面は自由入力じゃなくて選択肢だろうという前提。
ACFもSCFもカスタムフィールド作成時に選択肢を仕込めるけど、その一覧を表示する機能はないっぽくて、だから手打ちしないといけない。値ごとにベタ打ちするのはダルいからforeachで回すのが最近の自分のトレンド。
<form action="【該当ページURL】" method="get">
<?php
$fields = array('***','***','***',...);
foreach ( $fields as $field ):
?>
<label><input type="radio" name="field" value="<?php echo $field; ?>"><?php echo $field; ?></label>
<?php endforeach; ?>
<button>送信する</button>
</form>
で、こう。
$field = $_GET['field'];
$param = array(
'post_type' => '【カスタム投稿スラッグ】',
'meta_query' => array(
array(
'key' => '【カスタムフィールド名】',
'value' => $field,
),
),
);
ページネーションとパラメータの話
今回の内容は絞り込み条件をパラメータに突っ込んで扱う方法を取ってる。
記事一覧だからいっぱいヒットする可能性は十分にある。何十件何百件ある記事を全部表示するのは流石にダルいので、ページネーションを入れたい。
パラメータが無いと絞り込みが動かないのだけど、ページネーションと共存できるのか。
結論、できる。
wp-pagenaviが入ってるページでURLにパラメータを足して更新すると、WP-PageNaviが生成したページネーションのリンクにもパラメータが入ってることが分かる。
調整が必要ないのでめっちゃ助かりますね。
データベースから引っ張る方法(SQL)
もはやWordpressの良さをぶち壊しにしてる気がするんだけど、一般的なPHPよろしくDBから直接引っ張る手段がある。
実用性が無くはないけどなんかもうWP案件なのかこれ?っていうモヤモヤ。
プラグインでやる
探せばもっとある。
ウィジェットとかブロックエディタに放り込めるらしい。カスタム投稿、カスタムフィールドに対応してるらしい。良いですね。ただ、どれもインストール数がそこまでないのでプラグインに頼ることは稀なんでしょう。
最近はプラグインを減らしたい派になってるのでちょっとためらいがある。
コメント