引き続き、特定のカテゴリ内で絞り込み検索を行う仕組みを構築していきたいと思います。
前回は検索条件に特定のカテゴリが含まれる場合、検索結果を処理するphpファイルを差し替えるところまで進めました。
ただ、現状では検索を実行するとチェックボックスの状態は元に戻ってしまいます。
絞り込み検索では、検索結果を見て条件を調整できる方が便利です。
今回は、引き続き絞り込み検索ができるように前回の検索条件を保持する仕組みを作っていきます。
目次:
チェックボックスの状態を管理する配列を準備する
WordPressの検索では既存のtagパラメーターへタグスラッグを入れると検索結果に反映されます。
tagパラメーターは複数のタグスラッグを指定できるのですが、取り出せるのは最後に指定した1つだけです。
チェックボックスの状態を管理用配列へ入れる
まずはチェックされたタグスラッグを管理するための配列を準備します。
ここはチェックボックスの値を入力先を配列に変更することで対応できます。ここでは配列を「compositionCheckdTags」としておきます。
修正前
$rtn_code = $rtn_code.'<label><input type="checkbox" name="tag" value="'.$tag->slug.'">'.$tag->name.'</label><br>';
修正後
$rtn_code = $rtn_code.'<label><input type="checkbox" name="compositionCheckdTags[]" value="'.$tag->slug.'">';
※nameの値を規定の「tag」パラメーターから、独自の「compositionCheckdTags」配列へ変更
管理用配列を検索パラメーターとして登録する
関数内で定義した配列の値は、関数の処理が終了した時点でなくなります。検索後に配列の値を持ち越せるように、独自の検索パラメーターとして登録します。
検索パラメータへ登録するコード
実装:function.php
// 独自のクエリパラメータを検索結果に反映する function search_filter($query) { if ($query->is_main_query()) { if ($query->is_search && in_category('composition')) { $query->set('tag',get_query_var('compositionCheckdTags')); } } } add_action( 'pre_get_posts','search_filter' );
これで、既存の検索パラメーターと同様に検索後も値を取得することができます。
タグスラッグを検索し、チェック状態にする
チェックされたタグスラッグを検索後に持ち越せるようになったので、チェックボックスを表示する際に確認し、前回のチェック状態を反映します。
管理用配列にはチェックされたタグスラッグだけが入っています。検索後にチェックボックスを再構築する際に、現在処理を行っているタグスラッグが管理用配列内に存在するかどうかを確認します。
PHPには配列内を検索する関数があります。
これを利用して管理用配列内に一致するタグスラッグがあれば、チェックボックスをチェック状態にする記述を追加します。
配列内検索関数「array_search」を使ってチェック状態を確認する
配列内検索関数は最初の値でヒットした場合「0」を返します。PHPのif文では「0=false」と判定されることに注意します。0を数値として扱いたい場合は、下記のコードのように「==」比較演算子を使います。
修正部分
$rtn_code = $rtn_code.'<label><input type="checkbox" name="compositionCheckdTags[]" value="'.$tag->slug.'"'; // 前回のチェック項目を確認 if (empty($checkTags) != true) { // スラッグがチェックされたかを確認 if (array_search($tag->slug,$checkTags) !== false){ $rtn_code = $rtn_code.' checked'; } } $rtn_code = $rtn_code.'>'.$tag->name.'</label><br>';
内容を補足します。
「array_search」関数を使って、現在処理しているタグスラッグで管理配列内を検索します。ヒットした場合はチェックボックスを表示するhtmlタグ<input>へ「checked」属性を付けてチェック状態にします。
これでチェックボックスの値は検索後も保持されるようになりました。
指定されたスラッグ名のカテゴリ内で使われるタグ一覧をチェックボックスとして表示するコード(チェック状態保持版)
実装:function.php
// 呼び出し用ショートコードの定義 add_shortcode('tagsInCategoryCheckList', 'tags_in_category_checkList'); // 指定カテゴリ内のタグ一覧を、チェックボックスで表示する function tags_in_category_checkList($atts) { extract(shortcode_atts(array( 'sulg_name' => "", ), $atts)); // ショートコードの引数処理 if ($sulg_name == "") { // 現在のカテゴリで設定 $cat_id = get_query_var( 'cat' ); $cat_slug = get_category($cat_id)->slug; }else{ // 指定のカテゴリで設定 $cat_slug = $sulg_name; $cat_id = get_category_by_slug($sulg_name)->cat_ID; } $rtn_code = $rtn_code.'<form method="get" id="searchform" action="'.home_url().'">'; $rtn_code = $rtn_code.'<label for="s" class="assistive-text">検索</label>'; $rtn_code = $rtn_code.'<input type="text" name="s" id="s" placeholder="検索" />'; // カテゴリ指定用(隠し入力欄) $rtn_code = $rtn_code.'<input type="hidden" name="category_name" value="'.$cat_slug.'">'; // 表示順はランダム(隠し入力欄) $rtn_code = $rtn_code.'<input type="hidden" name="orderby" value="rand">'; $rtn_code = $rtn_code.'<div>タグ</div>'; // 前回チェックされたタグ情報を取得 $checkTags = get_query_var('compositionCheckdTags'); $tags = my_tags_in_cat($cat_id); foreach($tags as $tag) { $rtn_code = $rtn_code.'<label><input type="checkbox" name="compositionCheckdTags[]" value="'.$tag->slug.'"'; // 前回のチェック項目を確認 if (empty($checkTags) != true) { // スラッグがチェックされたかを確認 if (array_search($tag->slug,$checkTags) !== false){ $rtn_code = $rtn_code.' checked'; } } $rtn_code = $rtn_code.'>'.$tag->name.'</label><br>'; } $rtn_code = $rtn_code.'<input type="submit" value="検索" id="compositionSubmit" />'; $rtn_code = $rtn_code.'</form>'; return $rtn_code; }
独自の検索パラメータを検索結果に反映する
チェックボックスの状態を独自の管理用配列に入れたため、そのままでは検索結果に反映されません。
独自の検索パラメーターの値を結果に反映する方法としては、検索結果を処理するphpファイル内でサブループを作り、該当記事の取得と表示を行うのが一般的です。サブループを使った方法は記述の自由度が高くなります。
ただ、今回は既存のtagパラメータに値を反映し直したいだけなので、記述するコードの量を抑える方向で実装したいと思います。
「pre_get_posts」アクションへのフック関数を準備する
具体的には「pre_get_posts」アクションにフックし、フック関数内でtagパラメータへ値を反映します。
既存のtagパラメータへ独自のパラメータの値を反映するコード
実装:function.php
// 独自のクエリパラメータを検索結果に反映する function search_filter($query) { if ($query->is_main_query()) { if ($query->is_search && in_category('composition')) { $query->set('tag',get_query_var('compositionCheckdTags')); } } } add_action( 'pre_get_posts','search_filter' );
これで再び、検索結果にチェックボックスの状態が反映されるようになりました。
以上で、特定のカテゴリ内で絞り込み検索を行うための改修は終了です。
まとめ
構想していた仕組みは作ることができました。
構図の要素については、まだ数を揃えられていないので今後は内容の充実を図っていきたいと思います。
また、ここまで自分でフォームを作ることがなかったので、とても良い勉強になりました。
タグは整理には便利なのですが、Wordpressでは基本的にサイト全体で使われているものが一覧になります。
カテゴリまで絞り込んだのであれば、今回の様にそのカテゴリないで使われているタグだけが見えたほうが情報を探すときは便利だと思います。
他のカテゴリにも流用できそうですので、また仕組みを検討していきたいと思います。
この断片があなたの星へ続く道を、少しでも照らすことを願って
連載記事
<参考>
WordPressの既存の検索パラメータについて
phpの配列内検索関数
「pre_get_posts」アクションへのフックについて