WP_Queryにタイトルを含みたい場合

WP_Queryにタイトルを含みたい場合

WordPressでサブクエリを作成する際にタイトルに指定の語句を含む検索例を紹介したいと思います。

データベースでLIKE句のような検索方法です。

紹介するのは二つの方法です。

  • クエリにWhere句を足す方法
  • 必要なものだけ先に抽出しておく方法

検索と同様に「’s’」をクエリに含むことでタイトルも検索されるのですが、これでは意図した動きをしません。

タイトル、抜粋、本文のOR検索が適応されているため、タイトルのみの検索ができないです。

クエリにWhere句を足す方法

一つ目の方法はクエリにWhere句を付与して検索する方法です。

フィルターフック「’posts_where’」を使用し、クエリのwhere句を変更が可能です。

add_filter( 'posts_where', $where );

タイトルに対して指定語句を検索する場合は「wp_posts」テーブルの「posts_title」を指定します。

function add_where( $where ) {
	global $wpdb;

	$like = '%' . '〇〇' . '%';
	$where .= $wpdb->prepare(" AND wp_posts.post_title LIKE %s", $like);

	return $where;
}

使用する際は他のクエリに影響が出ないように使用するサブクエリの前後でadd、removeを行います。

$args = [
				'post_type'      => 'post',
				'posts_per_page' => 10,
				'paged'          => $paged,
				'orderby'        => 'date',
				'order'          => 'DESC',
				'category__in'   => $cat_id,
			];
			add_filter( 'posts_where', 'add_where' );
			$query = new WP_Query( $args );
			remove_filter( 'posts_where', 'add_where');

こちらは比較的シンプルで、処理速度にも影響がないのではないかと思います。

必要なものだけ先に抽出しておく方法

こちらの方法では先に必要なものを抽出しおく方法です。

具体的にはループで該当する投稿IDのみ抽出、サブクエリのループで「post__in」に抽出した投稿IDを指定するという方法です。

$args = [
				'post_type'      => 'post',
				'posts_per_page' => -1,
				'orderby'        => 'date',
				'order'          => 'DESC',
				'category__in'   => $cat_id,
];
$query = new WP_Query( $args );
$post_in_id = [];
if( $query->have_posts() ) : while( $query->have_posts() ) : $query->the_post();
        if( ! preg_match('/○○/', get_the_title() ) ) continue;
				$post_in_id[] = $post->ID;
endwhile; endif;
wp_reset_postdata();

あらかじめ取得する場合、posts_per_pageで全件取得をしておきます。また、pagesは入れないようにしておきます。

preg_matchなどを使用し、当てはまるもののみ配列に入れます。

//上記続きの場合
        $args['post__in']  = $post_in_id;
				$args['paged']  = $paged;
				$args['posts_per_page'] = 10;
if( $query->have_posts() ) : while( $query->have_posts() ) : $query->the_post();

先ほど抽出したものも含めてオプション配列の内容を変更します。

ここで、実際表示のための「posts_per_page」や「paged」も指定します。

後は、通常のループのように扱います。

さいごに

後者の方法より前者の方がスマートな気がします。

ただ、前者で対応できないケースもあるかもしれませんので、その場合は後者を使用してください。