※社内専用

カスタムフィールドを用いて複雑な絞り込み機能を実装する

  • HOME
  • Education
  • カスタムフィールドを用いて複雑な絞り込み機能を実装する

カスタムフィールドを用いて投稿記事の絞り込み機能を実装する機会があったので、実装方法を備忘録として、残しておきます。
似たような実装依頼があった際に、参考にしてください。

下記が実装したサイトです。
http://s10013272000455.c31.hpms1.jp/category/case

実装サイトでは下記のような感じになります。

cssは今回は端折ります。
スタイルはサイトに合わせてください。

今回の絞り込み機能の仕組み

絞り込みの仕組みは下記の通りです。

絞り込み用のカスタムフィールドを用意

各記事でカスタムフィールドを入力・選択

絞り込みフィールドに、カスタムフィールドの値に基づいた選択項目を表示

絞り込みフィールドから値を選択

絞り込みボタン押下で、画面遷移、フィールドで選択した値をURLのパラメーターとして付与

パラメーターの値をもとに、記事を絞り込み、絞り込んだ記事を出力

上記のように、パラメーターで絞り込みの値を送信、取得して、記事を絞り込みます。

実装手順

絞り込み用のカスタムフィールドを追加

絞り込みで使うカスタムフィールドを追加します。

参考サイトでは、「ユニット台数」と「導入サービス」という二つのカスタムフィールドの値を絞り込みに使っています。

・ユニット台数 → フィールド名:unit_count フィールドタイプ:数値
・導入サービス → フィールド名:related_service_checkbox フィールドタイプ:チェックボックス

上記のような感じです。

カスタムフィールドの内容は、自身の実装するサイトに合わせて、内容を変えてください。

フィールド名やフィールドタイプなども項目に合わせて、適宜変えてください。

絞り込み対象のカテゴリーのテンプレファイル追加

参考サイトでは、「導入事例」カテゴリー(スラッグ名:case)の投稿で絞り込みを実装しています。

このカテゴリーは適宜変えてください。

もしくは、特定のカテゴリーに限らず、全ての投稿記事に対して、絞り込みを実装する場合は、次に紹介するテンプレファイルの追加は、「archive.php」に適用してください。

テーマフォルダ直下に「category-case.php」を追加して下記のように追記してください。
※自身のカテゴリーに合わせて、ファイル名変えてください

@layout('view.master')

@section('content')

<section class="sec_sort">
  <div class="container gutters">
    <h2 class="ani02 wow">条件で絞り込む</h2>
    <div class="sort_wrap">
      <form action="/case_result">
        <div class="row tile unit_count_radio_wrap">
          <div class="col span_2">
            <p class="title_text">ユニット台数</p>
          </div>
          <div class="col span_10">
            <ul>
              <li>
                <input type="radio" value="1~3台" name="unit_count" id="unit_count1">
                <label for="unit_count1">1~3台</label>
              </li>
              <li>
                <input type="radio" value="4~8台" name="unit_count" id="unit_count2">
                <label for="unit_count2">4~8台</label>
              </li>
              <li>
                <input type="radio" value="9~15台" name="unit_count" id="unit_count3">
                <label for="unit_count3">9~15台</label>
              </li>
              <li>
                <input type="radio" value="16台以上" name="unit_count" id="unit_count4">
                <label for="unit_count4">16台以上</label>
              </li>
            </ul>
          </div>
        </div>
        <div class="row tile service_check_wrap">
          <div class="col span_2">
            <p class="title_text">導入サービス</p>
          </div>
          <div class="col span_10">
            <ul>
              <li>
                <input type="checkbox" value="EPARK歯科メディア" id="service1" name="service[]">
                <label for="service1">EPARK歯科メディア</label>
              </li>
              <li>
                <input type="checkbox" value="EPARK歯科台帳" id="service2" name="service[]">
                <label for="service2">EPARK歯科台帳</label>
              </li>
              <li>
                <input type="checkbox" value="LINEサービス" id="service3" name="service[]">
                <label for="service3">LINEサービス</label>
              </li>
              <li>
                <input type="checkbox" value="HP制作" id="service4" name="service[]">
                <label for="service4">HP制作</label>
              </li>
              <li>
                <input type="checkbox" value="提携サービス" id="service5" name="service[]">
                <label for="service5">提携サービス</label>
              </li>
            </ul>
          </div>
        </div>
        <div class="row btn">
          <div class="col span_4 offset_2">
            <button>絞り込む</button>
          </div>
          <div class="col span_4">
            <p id="clear_btn">クリア</p>
          </div>
        </div>
      </form>
    </div>
  </div>
  <script>
    $(function() {
      $("#clear_btn").on("click", function(){
        $("input[type=\"checkbox\"]").prop("checked", false);
        $("input[type=\"radio\"]").prop("checked", false);
      })
    })
  </script>
</section>
<section>
  <div class="container gutters">
    <div class="row row_inline case_archive_list">
    @wpposts
    //ここにループで記事一覧のソースを記述(今回は端折ります)
      @wpempty
    @wpend
    </div>
    {{epress_pagination()}}
  </div>
</section>

@endsection

テンプレには、絞り込みフォーム部分とループの記事一覧のhtmlソースを記述してあります。

絞り込みフォーム部分は、自身のカスタムフィールドの内容に合わせて、適宜変更してください。

絞り込み検索結果ページの追加

絞り込み用の検索結果ページを固定ページで用意する必要があります。

まず、下記の内容で、固定ページを追加してください。

ページ名:絞り込み結果
スラッグ:result

固定ページを追加したら、ページのテンプレを作成します。

テーマフォルダ直下に「page-result.php」ファイルを追加して、下記のように記述してください。

@layout('view.master')

@section('content')
  @wpposts
  {{the_content()}}
  <?php
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    //パラメーター取得
    $param_unit_count = isset($_GET['unit_count']) ? sanitize_text_field($_GET['unit_count']) : '';
    $param_service = isset($_GET['service']) ? array_map('sanitize_text_field', $_GET['service']) : [];
  ?>
  <section class="sec_sort">
  <div class="container gutters">
    <h2 class="ani02 wow">条件で絞り込む</h2>
    <div class="sort_wrap">
      <form action="/case_result">
        <div class="row tile unit_count_radio_wrap">
          <div class="col span_2">
            <p class="title_text">ユニット台数</p>
          </div>
          <div class="col span_10">
            <ul>
              <li>
                <input type="radio" value="1~3台" name="unit_count" id="unit_count1"<?php if($param_unit_count == "1~3台"){echo ' checked';} ?>>
                <label for="unit_count1">1~3台</label>
              </li>
              <li>
                <input type="radio" value="4~8台" name="unit_count" id="unit_count2"<?php if($param_unit_count == "4~8台"){echo ' checked';} ?>>
                <label for="unit_count2">4~8台</label>
              </li>
              <li>
                <input type="radio" value="9~15台" name="unit_count" id="unit_count3"<?php if($param_unit_count == "9~15台"){echo ' checked';} ?>>
                <label for="unit_count3">9~15台</label>
              </li>
              <li>
                <input type="radio" value="16台以上" name="unit_count" id="unit_count4"<?php if($param_unit_count == "16台以上"){echo ' checked';} ?>>
                <label for="unit_count4">16台以上</label>
              </li>
            </ul>
          </div>
        </div>
        <div class="row tile service_check_wrap">
          <div class="col span_2">
            <p class="title_text">導入サービス</p>
          </div>
          <div class="col span_10">
            <ul>
              <li>
                <input type="checkbox" value="EPARK歯科メディア" id="service1" name="service[]"<?php if(in_array("EPARK歯科メディア",$param_service)){echo ' checked';} ?>>
                <label for="service1">EPARK歯科メディア</label>
              </li>
              <li>
                <input type="checkbox" value="EPARK歯科台帳" id="service2" name="service[]"<?php if(in_array("EPARK歯科台帳",$param_service)){echo ' checked';} ?>>
                <label for="service2">EPARK歯科台帳</label>
              </li>
              <li>
                <input type="checkbox" value="LINEサービス" id="service3" name="service[]"<?php if(in_array("LINEサービス",$param_service)){echo ' checked';} ?>>
                <label for="service3">LINEサービス</label>
              </li>
              <li>
                <input type="checkbox" value="HP制作" id="service4" name="service[]"<?php if(in_array("HP制作",$param_service)){echo ' checked';} ?>>
                <label for="service4">HP制作</label>
              </li>
              <li>
                <input type="checkbox" value="提携サービス" id="service5" name="service[]"<?php if(in_array("提携サービス",$param_service)){echo ' checked';} ?>>
                <label for="service5">提携サービス</label>
              </li>
            </ul>
          </div>
        </div>
        <div class="row btn">
          <div class="col span_4 offset_2">
            <button>絞り込む</button>
          </div>
          <div class="col span_4">
            <p id="clear_btn">クリア</p>
          </div>
        </div>
      </form>
    </div>
  </div>
  <script>
    $(function() {
      $("#clear_btn").on("click", function(){
        $("input[type=\"checkbox\"]").prop("checked", false);
        $("input[type=\"radio\"]").prop("checked", false);
      })
    })
  </script>
</section>
<section>
  <div class="container gutters">
    <div class="row row_inline case_archive_list">
    <?php
// unit_countの範囲を判定するための条件を設定
$meta_query = [];

// unit_countの条件を追加
if ($param_unit_count) {
    $unit_ranges = [
        '1~3台' => [1, 3],
        '4~8台' => [4, 8],
        '9~15台' => [9, 15],
        '16台以上' => [16, PHP_INT_MAX],
    ];

    if (array_key_exists($param_unit_count, $unit_ranges)) {
        $meta_query[] = [
            'key' => 'unit_count', //カスタムフィールド名
            'value' => $unit_ranges[$param_unit_count],
            'compare' => 'BETWEEN',
            'type' => 'NUMERIC',
        ];
    }
}

// serviceの条件を追加
if (!empty($param_service)) {
    $service_meta_query = [];

    foreach ($param_service as $service_value) {
      // デバッグ: サービス投稿の存在を確認
      $service_meta_query[] = [
        'key' => 'related_service_checkbox', //カスタムフィールド名
        'value' => '"' . $service_value . '"',
        'compare' => 'LIKE',
      ];
  }

    if (!empty($service_meta_query)) {
        // ANDの条件を作成
        $meta_query[] = [
            'relation' => 'AND',
        ];
        // 追加: 各条件をマージ
        foreach ($service_meta_query as $service_condition) {
            $meta_query[] = $service_condition;
        }
    }
}

$args = [
    'post_type' => 'post',
    'meta_query' => $meta_query,
    'paged' => $paged,
    'category_name' => "case",
];

$query = new WP_Query($args);

      if ($query->have_posts()){
        while ($query->have_posts()):
            $query->the_post();
      ?>
      //ここにループで記事一覧のソースを記述(今回は端折ります)
      <?php endwhile; ?>
      </div>
      <div class="pagenation">
        <?php
          $big = 999999999;
          echo paginate_links(array(
              'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
              // 'format' => '?paged=%#%&unit_count=' . urlencode($unit_count) . '&service[]=' . urlencode(implode('&service[]=', $service)),
              'format' => '?paged=%#%&unit_count=' . urlencode($unit_count),
              'current' => max(1, get_query_var('paged')),
              'total' => $query->max_num_pages,
              'prev_text' => '',
              'next_text' => ''
          ));
        ?>
      </div>
      <?php } else { ?>
        <p>導入事例が見つかりませんでした。</p>
      <?php } ?>
      <?php wp_reset_postdata(); ?>
  </div>
</section>
    @wpempty
  @wpend
@endsection

テンプレの中には、先ほどと同様の絞り込みフォームとループの記事一覧、ページネーションを記述しています。

また、上部に、パラメーターが付いていたら、その値を取得する処理を入れています。

パラメーターは下記の二つです。

・unit_count
・service

絞り込み箇所では、二つのパラメーターの値にそれぞれ絞り込み条件を指定しています。

パラメーター「unit_count」の値は、入力された数値が4パターンの範囲(「1~3台」「4~8台」「9~15台」「16台以上」)のどれかに属するかを絞り込み条件としています。

パラメーター「service」の値は、複数あることが想定されているので、値が複数あった場合は配列になります。serviceパラメーターで受け取った値に、カスタムフィールド「related_service_checkbox」で選択した値が含まれていた場合かどうかを絞り込み条件としています。

この絞り込みの条件の部分は、自身の制作しているサイトに合わせた内容に変えてください。