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_id
FROM {$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 1
FROM {$wpdb->postmeta}
WHERE {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID
AND {$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というか高めるため。
よく技術的なコンテンツのサイト・ページを見ると古い情報で使えないってことなどがあるが、書いた日もそうだが最終更新を記述してコンテンツの新鮮度(?)を表した方が良いからで、適宜投稿か更新か削除かすれば良い。
ソート順だが最終更新日順なのでこれも適宜変えれば良い。
検索窓は適当に、デフォルトでもいいし。
一応自実装してるが、環境・テーマでは不具合出るかも。