自定义文章类型(含两类自定义分类法)的搜索自动补全功能实现问询
自定义文章类型(含两类自定义分类法)的搜索自动补全功能实现问询
嘿,我来帮你搞定这个问题~ 你现在的代码核心问题是不管搜索什么内容,最后都会把文章标题的结果清空,只返回分类匹配项,所以没法区分用户是在搜文章标题还是分类名称。咱们调整下逻辑就能实现你要的效果:当搜索词匹配文章标题时显示标题列表,没有匹配标题时再显示分类名称列表。
第一步:修正PHP逻辑,区分文章标题与分类的搜索结果
把你的PHP代码改成下面这样,重点是保留文章标题的匹配结果,再根据情况返回对应内容:
function title_filter( $where, &$wp_query ){ global $wpdb; if ( $search_term = $wp_query->get( 's' ) ) { // 改用wpdb->prepare写法,更安全规范 $search_term = $wpdb->esc_like( $search_term ); $where .= $wpdb->prepare( ' AND ' . $wpdb->posts . '.post_title LIKE %s', '%' . $search_term . '%' ); } return $where; } function search_auto_sugg($option, $search) { $result = array(); foreach ($option as $s) { if (stripos($s, $search) !== false) { // stripos不区分大小写 array_push($result, $s); } } return $result; } function ja_ajax_search() { // 先做安全校验:检查搜索词是否存在 if (!isset($_POST['search']) || empty($_POST['search'])) { wp_send_json_error('请输入搜索内容'); } $search_key = sanitize_text_field(stripslashes($_POST['search'])); // 1. 查询匹配文章标题的结果 add_filter('posts_where', 'title_filter', 10, 2); $results = new WP_Query(array( 'post_type' => array('travel'), 'post_status' => 'publish', 'posts_per_page' => -1, 's' => $search_key )); remove_filter('posts_where', 'title_filter', 10, 2); $post_title_items = array(); if ($results->have_posts()) { while ($results->have_posts()) : $results->the_post(); $post_title_items[] = get_the_title(); endwhile; } wp_reset_postdata(); // 提前重置查询,避免影响后续分类查询 // 2. 查询匹配分类名称的结果 $domestic_travel = array( 'taxonomy' => 'domestic_travel', 'orderby' => 'name', 'show_count' => 0, 'pad_counts' => 0, 'hierarchical' => 1, 'title_li' => '', 'hide_empty' => 1 ); $international_travel = array( 'taxonomy' => 'international_travel', 'orderby' => 'name', 'show_count' => 0, 'pad_counts' => 0, 'hierarchical' => 1, 'title_li' => '', 'hide_empty' => 1 ); $synonyms_cat = get_categories($international_travel); $related_search_cat = get_categories($domestic_travel); $margeArray = array(); $margeArray2 = array(); foreach ($synonyms_cat as $val) { $margeArray[] = $val->name; } foreach ($related_search_cat as $val_search) { $margeArray2[] = $val_search->name; } $margeArray_twoArray = array_merge($margeArray, $margeArray2); $taxonomy_items = search_auto_sugg($margeArray_twoArray, $search_key); // 3. 判断返回哪类结果:优先返回文章标题,无匹配则返回分类 if (!empty($post_title_items)) { wp_send_json_success($post_title_items); } else { wp_send_json_success($taxonomy_items); } } add_action( 'wp_ajax_search_site', 'ja_ajax_search' ); add_action( 'wp_ajax_nopriv_search_site', 'ja_ajax_search' );
第二步:优化JavaScript代码(提升兼容性与安全性)
把JS里的AJAX地址写法调整得更规范,避免短标签兼容性问题:
jQuery(function($){ var searchRequest; // 定义正确的WordPress AJAX接口地址 var ajaxUrl = '<?php echo esc_url(admin_url("admin-ajax.php")); ?>'; $('.search-autocomplete').autoComplete({ minChars: 1, source: function(term, suggest){ // 取消之前未完成的请求,避免重复返回结果 try { searchRequest.abort(); } catch(e){} searchRequest = $.post(ajaxUrl, { search: term, action: 'search_site' }, function(res) { if(res.success){ suggest(res.data); } }); } }); });
逻辑说明
- 当用户输入的内容匹配到
travel类型的文章标题时,自动补全列表会优先显示这些文章标题; - 如果没有匹配的文章标题,系统会自动检查是否匹配
domestic_travel或international_travel分类的名称,显示对应的分类列表; - 新增了安全处理:比如校验搜索词是否为空、过滤用户输入、防止SQL注入、处理AJAX地址转义等,避免漏洞。
备注:内容来源于stack exchange,提问作者Subrata
相关产品推荐
相关产品推荐

