プラグインなしでカスタムフィールドの値を検索範囲に反映させる方法

スポンサーリンク

WelcartなどでECサイトを運営していると、メーカーの品番やSKUのコードを検索に反映させたい場合が結構あります。

しかし、Welcartが使っているWordPressの検索機能は「タイトル」と「コンテンツ」のみからキーワードを探すだけです。metaデータに格納されているSKU・品番などは、そのままでは検索されません。

データベースのpostmeta

データベースのpostmetaテーブルにデータが入っています

また、ECサイトでなくても、Advanced Custom Fields等でカスタムフィールドを使ったデータを使っている場合にも、それらを検索に反映させたい場合も少なからずあると思います。

このようなmetaデータを検索範囲に入れる方法は、世界中のエンジニアさん方がチャレンジしているようでコードも多く出ていますが、いくつも試した中ようやく動いたのがこちらのブログで紹介されていたコード。

Search ALL Custom Fields in WordPress – Deluxe Blog Tips

これでもう、プラグインに頼る必要がないです(=表示速度が早くなる=検索順位も良くなる)。というわけで早速シェアします。

ちなみにブログの著者の方はベトナムのエンジニアさんだそう。この時代、ブログは英語で書いてなんぼですね・・・。

もくじ

  1. search.phpを用意
  2. ループの外側のコードを置き換え
  3. 出力データのカスタマイズ
  4. まとめ

1. search.phpを用意

この方法は、functions.php等に書き込まず、search.php内に直接書き込んでクエリをコントロールします。search.phpは検索結果を表示させるWordPressのテンプレートです。

※search.phpがない場合は、index.phpが検索結果用のテンプレートとして読み込まれます。ここはカスタマイズ性を考えて、index.phpをコピーしてsearch.phpを作っておいたほうが良いでしょう。

search.phpのつくり

通常、search.phpはアーカイブページ(category.phpなど)と同様、ループ処理を行い、条件に合致する投稿を繰り返し表示させます。

ループさせる内容は、投稿タイトルやサムネイル、抜粋などであったりします。

<?php if(has_posts()): while(has_posts()): the_post(); ?>
//ここにループさせる内容
<?php endwhile; else: ?>
//ここに検索キーワードと一致する記事がない場合の表示
<?php endif; ?>

アーカイブページと違うのは、<?php endwhile; else: ?>で分岐して(上のコードで言うと3行目)、検索キーワードを含む投稿がひとつもない場合の表示をさせているところです。

通常、search.phpは投稿タイトルと内容のみからキーワードを探しますが、今回のコードではmetaデータを加えた検索クエリに変更するコードを、最初のif文の前に加えています。

2. ループの外側のコードを置き換え

というわけで、ループの中身はそのままに、ループの外側を以下のように書き換えます。

<?php
global $wpdb;
// If you use a custom search form
// $keyword = sanitize_text_field( $_POST['keyword'] );
// If you use default WordPress search form
$keyword = get_search_query();
$keyword = '%' . like_escape( $keyword ) . '%'; // Thanks Manny Fleurmond
// Search in all custom fields
$post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
    SELECT DISTINCT post_id FROM {$wpdb->postmeta}
    WHERE meta_value LIKE '%s'
", $keyword ) );
// Search in post_title and post_content
$post_ids_post = $wpdb->get_col( $wpdb->prepare( "
    SELECT DISTINCT ID FROM {$wpdb->posts}
    WHERE post_title LIKE '%s'
    OR post_content LIKE '%s'
", $keyword, $keyword ) );
$post_ids = array_merge( $post_ids_meta, $post_ids_post );
// Query arguments
$args = array(
    'post_type'   => 'post',
    'post_status' => 'publish',
    'post__in'    => $post_ids,
);
$query = new WP_Query( $args );
if ( $query->have_posts() ): while ( $query->have_posts() ) : $query->the_post(); ?>
//ここにループさせる内容
<?php endwhile; else: ?>
//ここに検索キーワードと一致する記事がない場合の表示
<?php endif; ?>

かなり長いコードですが、「//ここにループさせる内容」以下は同じです。間違えないようにsearch.phpを書き換えます。

3. 出力データのカスタマイズ

上記コードでは、21~25行目の$args=array();で、検索クエリを以下のように設定しています。

  • 投稿タイプ→投稿(固定ページを含まない)
  • 投稿ステータス→公開済み

これらに、更に条件を加えることも可能です。

例えばカテゴリーを「商品(スラッグ:item)」に限定するなら、

'category_name' => 'item',

array()内に加えます。※最後のカンマ「,」をお忘れなく。

その他詳しい設定内容は、以下のサイトをご参照下さい。

関数リファレンス/WP Query ー WordPress Codex 日本語版

4. まとめ

Search Everythingなどの検索範囲拡張のプラグインも既にありますが、この方法ならばプラグインの導入が不要となるので、プラグイン同士の余計な不具合等の心配がなくなります。

カスタムフィールドは、ECサイトでなくても、不動産サイトであれば物件の住所や間取り、アートや文芸系サイトであれば作者名や年代など、それぞれに重要なデータを入力しておくことが多いと思います。

それらのデータは検索でヒットさせるべき内容にもなり得るので、このようなカスタマイズは多くのデータを取り扱うWebサイトでは有用です。

6 Responses to “プラグインなしでカスタムフィールドの値を検索範囲に反映させる方法”

  1. […] プラグインなしでカスタムフィールドの値を検索範囲に反映させる方法 | Welcart カスタマイズ […]

  2. akashi より:

    1年前の記事にコメント、失礼します;いつもお世話になっております。
    カスタムフィールドの値を検索に含めたいと「wordpress カスタムフィールド 検索」などと調べてましたら・・・おお~!既にまめ子さまが書いておられる!Welcart以外にも対応しているのでしょうけど、なんだか心強くなってさっそく使わせていただきました!コピペだけでいけました。天使のようなお方です~

    • まめ子(管理人) より:

      わざわざコメントを有難うございます。しかしながらコードを作ったのはそのベトナムのコーダーさんですから・・・^^;コードのヒントを探す時は、英語で検索すると結構見つかりますよ!

  3. sumito より:

    こちら参考にさせていただきましたが、
    1件もヒットしない場合に全件が出力されてしまうという結果になってしまいます。

    • まめ子(管理人) より:

      そうなんですか・・・ベトナムのそのエンジニアの方のページに何かヒントはないでしょうかね?(すみません、検証する余裕が全くないもので・・・)何かお分かりになりましたらシェア頂けると助かりますm(_ _)m

Copyright© 2017 Welcart カスタマイズ ブログ All Rights Reserved.