WordPressカスタム投稿を検索結果に表示させるためには
カスタム投稿(post_typeがpostやpage以外)を検索結果に含まれたい場合があります。
やり方について、ひと苦労しましたので、メモします。
■方法1
pre_get_postsフィルタを利用し、post_typeを指定する方法。
function.php
1 2 3 4 5 6 7 8 9 10 |
function filter_pre_search( $query ) { if( is_admin() || ! $query->is_main_query() ){ return; } if( $query->is_search() || $query->is_home()){ // search page $query->set( 'post_type', array( 'post', 'page', 'mypost') ); } } add_filter( 'pre_get_posts', 'filter_pre_search' ); |
search.php
※この方法の場合、search.phpでは、メインクエリを利用しますので、そのまま変更なしでご利用頂けます。
■方法2
posts_searchフィルタを利用し、post_typeを指定する方法。
※おまけに、キーワード指定した場合の検索例
function.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
function custom_search($search, $wp_query) { global $wpdb; if (!$wp_query->is_search) return $search; if (!isset($wp_query->query_vars)) return $search; $search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : ''); if ( count($search_words) > 0 ) { $search = ''; $search .= "AND post_type IN ('post', 'page', 'mypost')"; foreach ( $search_words as $word ) { if ( !empty($word) ) { $search_word = '%' . esc_sql( $word ) . '%'; $search .= " AND ( {$wpdb->posts}.post_title LIKE '{$search_word}' OR {$wpdb->posts}.post_content LIKE '{$search_word}' OR {$wpdb->posts}.ID IN ( SELECT distinct post_id FROM {$wpdb->postmeta} WHERE meta_value LIKE '{$search_word}' )) "; } } } return $search; } add_filter('posts_search','custom_search', 10, 2); |
search.php
※この方法の場合、search.phpでは、メインクエリを利用しますので、そのまま変更なしでご利用頂けます。
■方法3
WP_Query(サブクエリ)を利用する方法
mysearch.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php $args = array( 'post_type' => array( 'post', 'page', 'mypost'), 's' => 'キーワード', 'no_found_rows' => true, ); ?> <?php $query = new WP_Query( $args ); var_dump($query->request); ?> <?php if( $query->have_posts() ) : ?> <?php while ( $query->have_posts() ) : $query->the_post();get_template_part( 'content','' ); ?> <?php endwhile; wp_reset_postdata(); ?> <?php else : ?> Nothing Found. <?php endif; ?> |
■方法4
SQL(サブクエリ)を自前で構築する方法。
mysearch.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php $sql = "SELECT {$wpdb->posts}.* FROM {$wpdb->posts} WHERE 1=1 AND (({$wpdb->posts}.post_type = 'post') OR ({$wpdb->posts}.post_type = 'mypost')) AND ({$wpdb->posts}.post_status = 'publish') AND ( {$wpdb->posts}.post_title LIKE '%キーワード%' OR {$wpdb->posts}.post_content LIKE '%キーワード%' OR {$wpdb->posts}.ID IN ( SELECT distinct post_id FROM {$wpdb->postmeta} WHERE meta_value LIKE '%キーワード%' ) ) ORDER BY {$wpdb->posts}.post_date DESC LIMIT 0, 5"; $news_posts = $wpdb->get_results( $sql ); if ( $news_posts ) { foreach ( $news_posts as $post ) { setup_postdata( $post ); echo the_title(); } wp_reset_postdata(); } else { echo 'NO DATA.'; } ?> |
通常の場合、
方法1と方法2を利用することをお勧めします。
複雑なクエリを構築する場合、
方法3か方法4を利用します。