如何让WP_Query在标题、描述、分类及标签中搜索关键词?
解决方案:扩展WordPress搜索范围至标题、摘要、分类(含子分类)及标签
修改后的DOM结构(中文适配)
<main> <h1>文章</h1> <form action="<?php echo get_page_url() ?>" method="get"> <label for="search">搜索</label> <input type="text" name="s" id="search" value="<?php the_search_query(); ?>" /> </form> <?php if ($posts->have_posts()) : ?> <div id="wrp-articles"> <?php while ($posts->have_posts()) : $posts->the_post() ?> <article> <div class="wrp-thumb"> <a href="<?php echo get_permalink() ?>"> <img src="<?php echo get_the_post_thumbnail_url() ?>" alt="<?php echo get_the_title() ?>"> </a> </div> <ul class="list-categories"> <?php foreach (get_the_category() as $cat) : ?> <li> <a href="<?php echo get_category_link($cat->term_id) ?>"><?php echo $cat->name ?></a> </li> <?php endforeach; ?> </ul> <span class="title"><?php echo get_the_title() ?></span> <p><?php echo get_the_excerpt() ?></p> </article> <?php endwhile; ?> </div> <?php endif; ?> <div id="pagination"> <?php echo paginate_links(array( 'base' => get_site_url() . '%_%', 'format' => '/page/%#%', 'total' => $posts->max_num_pages, 'current' => max(1, get_query_var('paged')) )) ?> </div> </main>
修改后的PHP代码(实现扩展搜索)
<?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; $search_term = ''; $args = array( 'post_type' => 'post', 'posts_per_page' => 3, 'order' => 'desc', 'paged' => $paged ); if (!empty($_GET['s'])) { $search_term = sanitize_text_field($_GET['s']); // 获取匹配关键词的分类(含子分类)ID $matching_cats = get_terms(array( 'taxonomy' => 'category', 'name__like' => $search_term, 'hide_empty' => false )); $cat_ids = array(); foreach ($matching_cats as $cat) { $cat_ids[] = $cat->term_id; // 追加子分类ID $child_cats = get_term_children($cat->term_id, 'category'); $cat_ids = array_merge($cat_ids, $child_cats); } $cat_ids = array_unique($cat_ids); // 获取匹配关键词的标签ID $matching_tags = get_terms(array( 'taxonomy' => 'post_tag', 'name__like' => $search_term, 'hide_empty' => false )); $tag_ids = wp_list_pluck($matching_tags, 'term_id'); // 添加临时过滤器修改查询逻辑 add_filter('posts_join', function($join) use ($wpdb) { // 关联分类/标签关系表 $join .= " LEFT JOIN {$wpdb->term_relationships} tr ON {$wpdb->posts}.ID = tr.object_id "; $join .= " LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id "; $join .= " LEFT JOIN {$wpdb->terms} t ON tt.term_id = t.term_id "; return $join; }); add_filter('posts_where', function($where) use ($wpdb, $search_term, $cat_ids, $tag_ids) { // 调整原搜索条件的逻辑连接符为OR $where = str_replace('AND (((', 'OR (((', $where); // 添加分类匹配条件 if (!empty($cat_ids)) { $cat_ids_str = implode(',', array_map('intval', $cat_ids)); $where .= " OR tt.taxonomy = 'category' AND tt.term_id IN ($cat_ids_str) "; } // 添加标签匹配条件 if (!empty($tag_ids)) { $tag_ids_str = implode(',', array_map('intval', $tag_ids)); $where .= " OR tt.taxonomy = 'post_tag' AND tt.term_id IN ($tag_ids_str) "; } return $where; }); // 添加去重规则,避免同一文章因关联多分类/标签重复显示 add_filter('posts_distinct', function() { return 'DISTINCT'; }); } $posts = new WP_Query($args); // 清理临时过滤器,避免影响后续查询 if (!empty($search_term)) { remove_filter('posts_join', '__return_false'); remove_filter('posts_where', '__return_false'); remove_filter('posts_distinct', '__return_false'); } ?>
核心逻辑说明
- 分类与子分类覆盖:通过
get_terms搜索匹配关键词的分类,再用get_term_children拉取所有子分类ID,确保包含子分类下的文章。 - 标签匹配:直接通过
get_terms筛选名称含关键词的标签ID。 - 临时过滤器:
posts_join关联分类/标签相关数据表,让查询能读取分类、标签信息;posts_where修改查询逻辑,将标题、摘要、分类、标签的匹配规则用OR连接;posts_distinct避免同一文章因关联多个分类/标签被重复输出。
- 过滤器清理:查询完成后立即移除临时过滤器,防止干扰页面其他WordPress查询。
内容的提问来源于stack exchange,提问作者fpdev
相关产品推荐
相关产品推荐

