wordpress 后台产品实现只搜索标题功能以及产品搜索分类排除,产品标签功能搜索

新的搜索功能,专门用于搜索产品标题:

// 添加搜索和筛选字段
function add_product_search_filters() {
    global $pagenow;
    
    if ($pagenow !== 'edit.php' || !isset($_GET['post_type']) || $_GET['post_type'] !== 'product') {
        return;
    }
    
    $title_search = isset($_GET['title_search']) ? sanitize_text_field($_GET['title_search']) : '';
    $exclude_cat = isset($_GET['exclude_category']) ? intval($_GET['exclude_category']) : '';
    $tag_filter = isset($_GET['tag_filter']) ? sanitize_text_field($_GET['tag_filter']) : '';
    
    ?>
    <div class="product-filters" style="display: inline-block; margin: 0 4px;">
        <input type="text" 
               name="title_search" 
               value="<?php echo esc_attr($title_search); ?>" 
               placeholder="搜索产品标题"
               style="margin-right: 4px;">
        
        <select name="exclude_category" style="margin-right: 4px;">
            <option value="">显示所有分类</option>
            <?php display_categories_recursive(); ?>
        </select>

        <select name="tag_filter" style="margin-right: 4px;">
            <option value="">全部产品</option>
            <option value="has_tag" <?php selected($tag_filter, 'has_tag'); ?>>有标签</option>
            <option value="no_tag" <?php selected($tag_filter, 'no_tag'); ?>>无标签</option>
        </select>
    </div>
    <?php
}
add_action('restrict_manage_posts', 'add_product_search_filters');

// 递归显示分类
function display_categories_recursive($parent = 0, $level = 0) {
    global $exclude_cat;
    
    $terms = get_terms(array(
        'taxonomy' => 'product_cat',
        'hide_empty' => false,
        'parent' => $parent
    ));
    
    foreach($terms as $term) {
        $indent = str_repeat('&nbsp;&nbsp;&nbsp;', $level);
        echo '<option value="' . esc_attr($term->term_id) . '" ' 
             . selected($exclude_cat, $term->term_id, false) . '>' 
             . $indent . '排除: ' . esc_html($term->name) 
             . '</option>';
        
        display_categories_recursive($term->term_id, $level + 1);
    }
}

// 处理搜索和筛选查询
function handle_product_search_query($query) {
    global $pagenow;
    
    if (!is_admin() 
        || $pagenow !== 'edit.php' 
        || !isset($_GET['post_type']) 
        || $_GET['post_type'] !== 'product'
        || !$query->is_main_query()) {
        return $query;
    }

    $tax_query = array();

    // 处理标题搜索
    if (isset($_GET['title_search']) && !empty($_GET['title_search'])) {
        $query->query_vars['meta_query'] = array();
        $query->query_vars['s'] = '';
        $query->query_vars['search_prod_title'] = sanitize_text_field($_GET['title_search']);
        add_filter('posts_where', 'filter_product_title', 10, 2);
    }

    // 处理分类排除
    if (isset($_GET['exclude_category']) && !empty($_GET['exclude_category'])) {
        $exclude_cat_id = intval($_GET['exclude_category']);
        
        $exclude_cats = array($exclude_cat_id);
        $child_terms = get_term_children($exclude_cat_id, 'product_cat');
        if (!is_wp_error($child_terms)) {
            $exclude_cats = array_merge($exclude_cats, $child_terms);
        }

        $tax_query[] = array(
            'taxonomy' => 'product_cat',
            'field' => 'term_id',
            'terms' => $exclude_cats,
            'operator' => 'NOT IN'
        );
    }

    // 处理标签筛选
    if (isset($_GET['tag_filter']) && !empty($_GET['tag_filter'])) {
        switch($_GET['tag_filter']) {
            case 'has_tag':
                $tax_query[] = array(
                    'taxonomy' => 'product_tag',
                    'operator' => 'EXISTS'
                );
                break;
            case 'no_tag':
                $tax_query[] = array(
                    'taxonomy' => 'product_tag',
                    'operator' => 'NOT EXISTS'
                );
                break;
        }
    }

    // 应用tax_query
    if (!empty($tax_query)) {
        if (count($tax_query) > 1) {
            $tax_query['relation'] = 'AND';
        }
        $query->set('tax_query', $tax_query);
    }

    return $query;
}
add_filter('pre_get_posts', 'handle_product_search_query');

// 标题搜索过滤器
function filter_product_title($where, $wp_query) {
    global $wpdb;
    
    if ($search_term = $wp_query->get('search_prod_title')) {
        $search_terms = array_filter(array_map('trim', explode(' ', $search_term)));
        $title_where = array();
        
        foreach($search_terms as $term) {
            if(!empty($term)) {
                if(is_numeric($term)) {
                    $title_where[] = $wpdb->prepare(
                        "({$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_title LIKE %s)",
                        $term . ' %',
                        '% ' . $term . ' %',
                        '% ' . $term,
                        '% ' . $term . '-'
                    );
                } else {
                    $title_where[] = $wpdb->prepare(
                        "({$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_title LIKE %s)",
                        $term . ' %',
                        '% ' . $term . ' %',
                        '% ' . $term
                    );
                }
            }
        }
        
        if (!empty($title_where)) {
            $where .= " AND (" . implode(' AND ', $title_where) . ")";
        }
    }
    
    remove_filter('posts_where', 'filter_product_title', 10);
    return $where;
}

// 添加样式
function add_product_filter_styles() {
    global $pagenow;
    if ($pagenow === 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] === 'product') {
        ?>
        <style>
            .product-filters select,
            .product-filters input[type="text"] {
                min-width: 150px;
                height: 30px;
                vertical-align: middle;
            }
        </style>
        <?php
    }
}
add_action('admin_head', 'add_product_filter_styles');

功能说明:

  1. 如果一个产品属于多个类目
  2. 只要其中一个类目被排除
  3. 该产品就不会显示在结果中
  4. 不管它是否同时属于其他未被排除的类目
  5. 标签筛选(有标签/无标签)

比如:

  • 产品同时属于类目A和类目B
  • 当排除类目B时
  • 这个产品将不会显示在结果中
  • 即使它也属于类目A

By 行政