Steamer Lane Studio技術備忘録WordPress

WordPressでACFによるカスタムフィールドで特定のフィールドを含めての検索 +固定ページ+カスタムポストver

wordpress WordPressでACFによるカスタムフィールドで特定のフィールドを含めての検索 +固定ページ+カスタムポストver
作成日: 2025年4月17日

色々やってると色々必要なものが発生する。
以前作ったものはpostにACFの指定フィールド内も参照させるものだったが、色々、サイト内検索の拡充などを進めるうち、タイトル通り検索対象を広拡充させる必要が出た。

仕様

  • AND検索 スペース区切り(半角・全角OK)
  • 対象:投稿・カスタム投稿・固定ページ(カスタム投稿はなくてもエラーを返さない)
  • 投稿はカテゴリー指定、固定は投稿ID指定で除外可能とする
  • 投稿・固定とも指定のACFでのカスタムフィールドも参照する(指定がない場合は空でもエラーを返さない)
  • WP6.7.2and up php8x 大概のレンタルサーバーなら動くと思う

こんな感じかな。サイトによるが、あった方が良い場合は特にインデックス登録される場合もある(あった)のでサイト内検索窓は付けてもいいかもね。

コード

function.php記述

function custom_search($search, $wp_query) {global $wpdb;

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

$search_words = explode(' ', isset($wp_query->query_vars['s']) ? trim($wp_query->query_vars['s']) : '');if (count($search_words) === 0) {return " AND 1=0 "; // 空検索時に結果ゼロ}

// 除外するカテゴリーID(post用)とページID(page用)$exclude_category_ids = [998, 999]; // 除外カテゴリーID ////////////////////////-*-使用時設定/確認-*-$exclude_page_ids = [998, 999]; // 除外ページID(01は1に修正) ////////////////////////-*-使用時設定/確認-*-

$search = '';$search .= " AND ({$wpdb->posts}.post_type = 'post' OR {$wpdb->posts}.post_type = 'page' OR {$wpdb->posts}.post_type = 'custom')";// カスタム投稿スラッグ指定 ////////////////////////-*-使用時設定/確認-*-

// postのカテゴリー除外if (!empty($exclude_category_ids)) {$exclude_cat_sql = implode(',', array_map('intval', $exclude_category_ids));$search .= " AND NOT ({$wpdb->posts}.post_type = 'post' AND {$wpdb->posts}.ID IN (SELECT object_idFROM {$wpdb->term_relationships}WHERE term_taxonomy_id IN ($exclude_cat_sql)))";}

// pageのID除外if (!empty($exclude_page_ids)) {$exclude_page_sql = implode(',', array_map('intval', $exclude_page_ids));$search .= " AND NOT ({$wpdb->posts}.post_type = 'page' AND {$wpdb->posts}.ID IN ($exclude_page_sql))";}

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 EXISTS (SELECT 1FROM {$wpdb->postmeta}WHERE {$wpdb->postmeta}.post_id = {$wpdb->posts}.IDAND {$wpdb->postmeta}.meta_key = 'access'AND {$wpdb->postmeta}.meta_value LIKE '{$search_word}')) ";////////////////////////////////////meta_key IN ('access')フィールド名を指定のフィールド名にする/////////////-*-使用時設定/確認-*-}}

error_log('Custom Search SQL: ' . $search);return $search;}add_filter('posts_search', 'custom_search', 10, 2);

これだけではAND検索時全角スペースが使えない、検索時全角=半角をイコールにするコードか、multibyte patchのようなプラグインが必要。

search.php記述

<?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;$args = array('s'              => get_search_query(),'posts_per_page' => 9,'orderby'       => 'modified','order'          => 'DESC','paged'          => $paged,);$query = new WP_Query($args);?>                <?php if ($query->have_posts()): ?>                <section>                    <h2>「<?php echo get_search_query(); ?>」での検索結果 <?php echo esc_html($rep2); ?></h2><?php while ($query->have_posts()): $query->the_post(); ?><div><a href="<?php the_permalink(); ?>"><picture>
<img src="<?php the_post_thumbnail_url('thumbnail'); ?>" alt="<?php echo esc_attr(get_the_title()); ?>"></picture><h3><?php the_title(); ?><?php $categories = get_the_category();if (!empty($categories)) {$category = $categories[0];if ($category->category_parent) {$parent_category = get_category($category->category_parent);$category_name = $parent_category->name;} else {$category_name = $category->name;}echo $category_name;}?><?php if (get_post_type() === 'custom') {echo 'カスタム';}?>最終更新日:<?php the_modified_date('Y年m月d日'); ?></h3><p><?php echo mb_strimwidth(strip_tags(get_the_excerpt()), 0, 100, '...', 'UTF-8');?></p></a></div><?php endwhile; ?>  </section><?php if ( pagination() ) {echo pagination();}?><?php else : ?><section><p>検索しましたが「<?php echo esc_html(get_search_query()); ?>」を含む記事はありません。</p></section><?php endif; ?><?php wp_reset_postdata(); ?>

ループ内のhtmlは適当に。
h3に書いたのは

  • タイトル
  • 投稿の場合属するカテゴリー、カスタムの場合は命名した名前(echo ‘カスタム’部分)表示
  • 最終更新日
  • excrept100文字

excerptはともかく、他はユーザーへの情報としてUIというか高めるため。
よく技術的なコンテンツのサイト・ページを見ると古い情報で使えないってことなどがあるが、書いた日もそうだが最終更新を記述してコンテンツの新鮮度(?)を表した方が良いからで、適宜投稿か更新か削除かすれば良い。
ソート順だが最終更新日順なのでこれも適宜変えれば良い。

検索窓は適当に、デフォルトでもいいし。
一応自実装してるが、環境・テーマでは不具合出るかも。