前回の記事でWordPressのサイト内検索の仕組みについて解説しました。

こちらがまだの方は、まず下記の記事で構造的な理解を深めてください。

【WordPress】サイト内検索の仕組みについて解説

今回の記事では、サイト内検索対象に「カスタムフィールド」を加える方法について解説します。

WordPressのデフォルトの検索機能では、カスタムフィールドが検索対象になっていません。

下記がデフォルト検索の際に実行されるクエリになりますが、

wp_posts.post_typeには「post」「page」「attachment」のみが指定されています。

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
WHERE 1=1
AND (((wp_posts.post_title LIKE '%検索キーワード%')
OR (wp_posts.post_excerpt LIKE '%検索キーワード%')
OR (wp_posts.post_content LIKE '%検索キーワード%')))
AND wp_posts.post_type IN ('post', 'page', 'attachment')
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_author = 1
AND wp_posts.post_status = 'private')
ORDER BY wp_posts.post_title LIKE '%検索キーワード%' DESC, wp_posts.post_date DESC
LIMIT 0, 10

WordPressで商品情報サイトを運営しているメーカーなどの場合、カスタムフィールドに型番などの情報を格納するケースがあります。

メーカーのサイト内検索では主に「商品名」「型番」が検索対象になることが多いため、

検索対象にカスタムフィールドを加えることができればユーザーが意図した検索結果を得ることができるでしょう。

実装

コードは他のサイトでも似たようなものがありますが、どの記述がそのような役割を持っているかを解説している記事は少ないので、細分化して解説していきます。

ソースコード

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 = 'post'";
        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}.ID IN (
                SELECT distinct post_id
                FROM {$wpdb->postmeta}
                WHERE {$wpdb->postmeta}.meta_key IN ('num') AND meta_value LIKE '{$search_word}'
                )
                ) ";
            }
        }
    }
    return $search;
}
add_filter('posts_search','custom_search', 10, 2);

解説

add_filter('posts_search','custom_search', 10, 2);

posts_searchというアクションフックを使用することで、WP_Queryでデータを取得する際のWHERE句をカスタマイズすることができます。

WHERE句にカスタムフィールドを含めるといったイメージです。

if (!$wp_query->is_search) return $search;
if (!isset($wp_query->query_vars)) return $search;

if (!$wp_query->is_search)で検索ページが表示されているかどうかを判定し

if (!isset($wp_query->query_vars))クエリ条件の設定の有無をチェックしています。

カスタムクエリ

$search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : '');

ここで検索キーワードをセットしています。
検索キーワードが1つ以上の場合に対応するために、半角スペース起点で配列を作成します。

SELECT distinct post_id
FROM {$wpdb->postmeta}
WHERE {$wpdb->postmeta}.meta_key IN ('num') AND meta_value LIKE '{$search_word}'

上記がカスタムフィールドを検索対象に指定するWHERE句になります。

SELECT distinctにpost_idを指定することで重複データを除外しています。

あとは$wpdb->postmetaでカスタムフィールドの指定を行い、

meta_value LIKE ‘{$search_word}’で検索ワードを含む文字列検索を行うことができます。

カテゴリー: WordPress