ワードプレス(WordPress)で前後の記事へのページネーションを実装する
ホームページに訪れた方のサイト内の滞留時間を高めるために、関連のある記事へのリンクを設置…
ワードプレスを使用して運用されているサイトで投稿した記事を検索したい(サイト内検索)というご相談を受けた際に調べた内容をメモ。
まずは、検索フォームを準備します。ソースを該当ページに直書きするでも良いですが、使いまわせるように別ファイル(searchform.php)で作成。
テーマ内にファイルをアップしたら、読み込み専用のソースで読み込みます。
<?php get_template_part('searchform'); ?>
今回はカスタム投稿から投稿された記事に対して、タグ、カテゴリー(カスタムタクソノミー)を使用して検索する方法を実装。
<form method="get" id="searchform" action="<?php bloginfo('url'); ?>">
<input type="hidden" name="s" id="s">
<input type="hidden" name="post_type" value="<?php echo get_post_type( $post ); ?>">
<select name='s-tag'>
<option value="">全てのタグ</option>
<?php
if($terms = get_terms('contents-tag')) {
foreach ( $terms as $term ) {
echo('<option value="'.esc_html( $term->slug ).'">'.esc_html($term->name).'</option>');
}
}
?>
</select>
<select name="s-cat">
<option value="">全てのカテゴリー</option>
<?php
if($terms = get_terms('contents-cat')) {
foreach ( $terms as $term ) {
echo('<option value="'.esc_html( $term->slug ).'">'.esc_html($term->name).'</option>');
}
}
?>
</select>
<input type="submit" value="検索">
</form>
ワードプレスの検索機能は「s」のパラメータ(キーワード検索)を基準に行われる、キーワードの指定が不要な場合でも「hidden」要素で「s」の値を返す必要があります。
また、一般的にサイト内検索では全てのページが対象となってしまうので、「name=”post_type”」の部分で該当する投稿タイプを限定しています。
ワードプレスで検索を行った際に表示されるページは「search.php」が使用されます。
そのままで良い場合は別として、検索結果ごとに表示するページを変更した場合は以下のコードを追加する必要があります。
function custom_template_include($template){
if(is_search()){
$post_types = get_query_var('post_type');
$new_template = locate_template(array('search-'.$post_types.'.php'));
if($new_template != ''){
return $new_template;
}
}
return $template;
}
add_filter('template_include', 'custom_template_include', 99);
上記コードを「function.php」に追記することで、他のページ同様に「search-○○○○(カスタム投稿名).php」が使用可能にできます。
<?php
// searchform.phpから送られてきたパラメーターを取得
$post_type = wp_unslash($_GET['post_type']);
$s-tag = wp_unslash($_GET['s-tag']);
$s-cat = wp_unslash($_GET['s-cat']);
// 絞り込み条件を追加
if($s-tag) {
$taxquery_tag = array(
'taxonomy' => 'contents-tag',
'terms' => $s-tag,
'field' => 'slug',
);
}
if($s-cat) {
$taxquery_cat = array(
'taxonomy' => 'contents-cat',
'terms' => $s-cat,
'field' => 'slug',
);
}
$args = array(
'post_type' => $post_type,
'paged' => get_query_var('paged'),
's' => get_search_query(),
'tax_query' => array(
'relation' => 'AND',
$taxquery_tag,
$taxquery_cat,
),
);
$sub_query = new WP_Query($args);
?>
<ul class="newslist__list">
<?php if ( $sub_query->have_posts() ) : ?>
<p><?php echo $sub_query->post_count; ?>件<span> / <?php echo $sub_query->found_posts; ?> 件</span></p>
<?php while ( $sub_query->have_posts() ) : $sub_query->the_post(); ?>
<!-- ここにループ処理 -->
<li>
<a href="<?php the_permalink(); ?>"><?php echo get_the_title(); ?></a>
</li>
<!-- ここまでループ処理 -->
<?php endwhile; ?>
</ul>
<nav class="pagination">
<?php
//ページネーション
$bignum = 999999999;
echo paginate_links( array(
'base' => str_replace( $bignum, '%#%', esc_url( get_pagenum_link($bignum) ) ),
'format' => '',
'current' => max( 1, get_query_var('paged') ),
'total' => $sub_query->max_num_pages,
'prev_text' => '←',
'next_text' => '→',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3
) );
?>
</nav>
<?php else: ?>
<p>検索されたキーワードにマッチする記事はありませんでした</p>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
「WP_Query」を使用して、条件に合った投稿リストを取得できるように値を設定。
リスト取得後は「wp_reset_postdata」使用して、変更していた取得条件をリセットしています。
特に指定のない場合は、タイトル、本文、抜粋が検索キーワードの対象となります。
正確性を増すため、本文のみに限定したい場合は下記を追記。
function search_by_title_only($query) {
if (!is_admin() && $query->is_main_query() && $query->is_search()) {
$query->set('post_type', 'post'); // 投稿タイプを限定する場合に記載
$query->set('search_title_only', true);
}
}
add_action('pre_get_posts', 'search_by_title_only');
function filter_search_by_title($where, $query) {
global $wpdb;
if ($query->get('search_title_only')) {
$search = $query->get('s');
if ($search) {
$where = " AND {$wpdb->posts}.post_title LIKE '%" . esc_sql($wpdb->esc_like($search)) . "%'";
}
}
return $where;
}
add_filter('posts_where', 'filter_search_by_title', 10, 2);