WordPressのアーカイブページに絞り込み検索機能をつける

WordPressのアーカイブページに絞り込み検索機能をつける方法を紹介します。
カスタム投稿タイプ(my_post_type)のアーカイブページをタクソノミー(my_tax)で絞り込みができるようにします。

テンプレートの作成

検索フォームと記事一覧を表示するテンプレートを作成します。
クエリパラメータがある場合は、チェックするようにします。

<form action="<?php echo esc_url(get_post_type_archive_link('my_post_type')); ?>" method="get">
  <!-- フリーワード検索 -->
  <input type="text" name="s" value="<?php echo get_search_query(); ?>">
<?php
  // ターム一覧をチェックボックスで表示
  $my_terms = get_terms('my_tax');
  if ( $my_terms ) :
?>
  <div>
<?php
    foreach ( $my_terms as $my_term ) :
      $checked = '';
      if ( isset($_GET['search_tax']) && is_array($_GET['search_tax']) && in_array($my_term->term_id, $_GET['search_tax']) ) {
        $checked = ' checked';
      }
?>
    <label>
      <input type="checkbox" name="search_tax[]" value="<?php echo esc_attr($my_term->term_id); ?>" <?php echo $checked; ?>>
      <span><?php echo $my_term->name; ?></span>
    </label>
<?php
    endforeach;
?>
  </div>
<?php
  endif;
?>
  <button type="submit">検索</button>
</form>
<?php
  // 記事を表示
  if ( have_posts() ) :
?>
<ul>
<?php
    while ( have_posts() ) : 
      the_post();
?>
  <li>
    <a href="<?php the_permalink(); ?>">
      <h2><?php the_title(); ?></h2>
      <p><?php the_content(); ?></p>
    </a>
  </li>
<?php
    endwhile;
?>
</ul>
<?php 
  else :
?>
<p>記事はありません。</p>
<?php
  endif;

検索をカスタマイズする

pre_get_postsアクションにフックを登録して、クエリパラメータがあれば検索をカスタマイズします。

function my_pre_get_posts( $query ) {
  do {
    if ( is_admin() ) break ;
    if ( ! $query->is_main_query() ) break ;

    if ( is_post_type_archive('my_post_type') ) {
      $tax_query = array();
      if ( isset($_GET['search_tax']) && is_array($_GET['search_tax']) ) {
        $tax_query[] = array(
          'taxonomy' => 'my_tax',
          'field' => 'id',
          'terms' => $_GET['search_tax'],
          'operator' => 'IN',
        );
      }
      if ( $tax_query ) {
        $query->set( 'tax_query' , $tax_query);
      }
      break ;
    }
  }
  while ( FALSE );
  return ;
}
add_action('pre_get_posts', 'my_pre_get_posts', 20);

以上で実装完了です。

コメント