WordPressをある程度使い込んでいる方ならご存じだと思いますが、標準のサイト内検索はカスタムフィールドの値を検索対象に含めません。
投稿タイトルや本文は検索対象になりますが、カスタムフィールド(postmetaテーブルに保存されるデータ)は検索対象外です。そのため、例えば次のようなケースでは検索が機能しません。
- 店舗情報サイトで住所や電話番号をカスタムフィールドに保存している
- 商品データの型番やSKUをカスタムフィールドで管理している
- ACFなどで拡張した情報を検索対象にしたい
特にデータ量が多いサイトほど、この仕様はかなり不便です。実際、私が運用しているサイトでも記事数が10万件近くあり、検索精度を上げるためにカスタムフィールド検索は必須でした。
そこで、
- プラグインで解決する方法
- functions.phpで直接対応する方法
この2つを実際に試しました。結果的に、最も安定して運用できた方法も含めて紹介します。
WPプラグイン「Search Everything」
まず最初に試したのが、有名な検索拡張プラグインSearch Everythingです。
古くから紹介されている定番プラグインで、カスタムフィールド検索にも対応しています。
プラグインで解決できるなら、それに越したことはありません。
管理画面から有効化するだけなので、導入も非常に簡単です。
- カスタムフィールドを検索対象に追加できる
- カテゴリやタグの検索も拡張可能
- 設定が比較的シンプル
ただし、私の環境では検索処理がかなり重くなりました。
記事数が多いサイトでは、検索クエリが大きくなりやすく、ページ表示が明らかに遅くなります。10万件規模の投稿+大量のカスタムフィールドがある環境では、正直実用レベルではありませんでした。
もちろん、小規模サイトであれば問題なく使える可能性があります。まずは試してみる価値はあると思います。
LINK Search Everything
WPプラグイン「Custom Fields Search by BestWebSoft」
次に試したのがCustom Fields Search by BestWebSoftというプラグインです。
このプラグインの特徴は、検索対象にするカスタムフィールドを細かく指定できる点です。つまり、必要なフィールドだけを検索対象にできます。
- 検索対象のカスタムフィールドを指定できる
- 不要なメタデータを除外できる
- 比較的軽量な検索処理
実際、導入当初は非常にうまく動作していました。
しかし、ある時期を境に突然動作しなくなりました。正確な原因は特定できていませんが、次のような可能性は考えられます。
- PHPバージョンの変更
- WordPress本体のアップデート
- プラグインの更新停止
現在はWordPress公式ディレクトリで配布されていないようなので、残念ながら使用を断念しました。プラグインは便利ですが、更新停止や互換性問題が発生するリスクは避けられません。
その結果、最終的に辿り着いたのが次の方法です。
functions.phpでカスタムフィールドを検索対象にする
最終的に採用したのはfunctions.phpに検索処理を追加する方法です。
WordPressの検索は内部的にSQLクエリを生成しています。そこで、その検索条件にpostmetaテーブルのmeta_valueを追加すれば、カスタムフィールドも検索対象にできます。
実際のコードはこちらです。
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}.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);
このコードをfunctions.phpに追加するだけで、カスタムフィールドの値も検索対象になります。
プラグインと違って余計な処理が入らないため、パフォーマンスも比較的安定しています。
参考:WordPressのサイト内検索でカスタムフィールドの内容も検索結果に含める方法
特定のカスタムフィールドだけ検索対象にする方法
サイトによっては、すべてのカスタムフィールドを検索対象にするとノイズが増える場合があります。
例えば次のようなデータです。
- 郵便番号
- 内部管理用のID
- アクセス情報
こうしたフィールドまで検索対象にすると、検索結果が意図しない形になることがあります。
その場合は、検索対象のフィールドを制御する方法が有効です。次のコードは、特定のカスタムフィールドを検索対象から除外する例です。
function cf_search_join($join) {
global $wpdb;
if (is_search()) {
$join. = ' LEFT JOIN '.$wpdb - > postmeta.
' ON '.$wpdb - > posts.
'.ID = '.$wpdb - > postmeta.
'.post_id ';
}
return $join;
}
add_filter('posts_join', 'cf_search_join');
function cf_search_where($where) {
global $wpdb;
if (is_search()) {
$where = preg_replace("/\(\s*".$wpdb - > posts.
".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/", "(".$wpdb - > posts.
".post_title LIKE $1) OR (".$wpdb - > postmeta.
".meta_value LIKE $1)", $where);
$where. = " AND (".$wpdb - > postmeta.
".meta_key NOT LIKE 'number')";
$where. = " AND (".$wpdb - > postmeta.
".meta_key NOT LIKE 'zip')";
$where. = " AND (".$wpdb - > postmeta.
".meta_key NOT LIKE 'access')";
}
return $where;
}
add_filter('posts_where', 'cf_search_where');
function cf_search_distinct($where) {
global $wpdb;
if (is_search()) {
return "DISTINCT";
}
return $where;
}
add_filter('posts_distinct', 'cf_search_distinct');
この方法を使えば、検索対象を細かくコントロールできます。
WordPress検索を拡張するならコード対応が最も安定
WordPressの検索機能は非常にシンプルですが、そのぶん拡張性は高い仕組みになっています。
今回試した結果をまとめると次の通りです。
- プラグインは手軽だが重くなる場合がある
- 更新停止のリスクがある
- 大規模サイトではパフォーマンス問題が出やすい
一方、functions.phpで対応する方法は次のメリットがあります。
- 処理内容を完全にコントロールできる
- 余計な処理が入らない
- 大規模サイトでも比較的安定する
WordPressはカスタムフィールドの活用が前提になっているCMSです。それにも関わらず、標準検索がカスタムフィールドを対象にしていないのは、正直なところ少し不便に感じます。
とはいえ、今回紹介した方法を使えば問題なく対応できます。
検索機能の精度はサイトの使いやすさに直結します。カスタムフィールドを多用しているサイトなら、ぜひ一度見直してみてください。
動画変換ソフト「Freemake Video Converter」のインストール方法と使い方
DNS切り替えによるメールサーバー移行手順と注意点を徹底解説
コメントはこちら