You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在侧边栏短代码的自定义筛选表单中修改WC query_vars?

实现WooCommerce产品标签多选筛选(key:value格式标签分组)

问题背景

通过短代码在侧边栏添加了自定义筛选表单,产品标签采用key:value格式,已实现拆分标签并按key分组为折叠菜单、提交时重新组合标签,但当前代码仅支持单个product_tag筛选。改成多选后,传递多个product_tag参数时,query_vars只会识别最后一个,需修改实现多选功能。

解决方案

要实现多选,需从表单字段命名、WordPress查询变量处理、表单提交逻辑三个维度修改:

1. 修改表单复选框name属性

将单个name="product_tag"改为数组格式name="product_tag[]",确保表单提交时能传递多个值:

// 原代码
<input class="ajax-checkbox" type="checkbox" value="' . $key . ':' . $argvalue . '" id="' . $id . '" name="product_tag" onChange="this.form.submit()" />

// 修改后
<input class="ajax-checkbox" type="checkbox" value="' . $key . ':' . $argvalue . '" id="' . $id . '" name="product_tag[]" onChange="handleFilterSubmit()" />

2. 用钩子处理多标签查询变量

WordPress默认不解析数组格式的查询参数,添加钩子将product_tag[]转换为query_vars可识别的格式,同时支持多标签的AND/OR逻辑(以下为AND逻辑,即同时匹配所有选中标签):

add_filter('query_vars', 'add_multiple_product_tag_var');
function add_multiple_product_tag_var($vars) {
    $vars[] = 'product_tag';
    return $vars;
}

add_action('pre_get_posts', 'handle_multiple_product_tags');
function handle_multiple_product_tags($query) {
    if (!is_admin() && $query->is_main_query() && is_shop()) {
        $product_tags = isset($_GET['product_tag']) ? $_GET['product_tag'] : [];
        if (!empty($product_tags) && is_array($product_tags)) {
            // 转换为标准化标签slug
            $tag_slugs = array_map(function($tag) {
                return sanitize_title($tag);
            }, $product_tags);
            
            // 设置多标签查询逻辑,如需OR匹配将'AND'改为'IN'
            $query->set('product_tag', $tag_slugs);
            $query->set('tag_operator', 'AND');
        }
    }
}

3. 修复表单提交逻辑(JavaScript)

原提交方式无法正确传递数组参数,改用FormData和URLSearchParams处理参数,同时保留搜索、排序等其他查询参数:

function handleFilterSubmit() {
    const form = document.getElementById('myfilter');
    const params = new URLSearchParams();
    
    // 收集选中的标签
    const productTags = form.querySelectorAll('input[name="product_tag[]"]:checked');
    productTags.forEach(tag => {
        params.append('product_tag[]', tag.value);
    });
    
    // 收集其他隐藏字段参数
    const hiddenFields = form.querySelectorAll('input[type="hidden"]');
    hiddenFields.forEach(field => {
        params.append(field.name, field.value);
    });
    
    // 跳转到筛选后的页面
    window.location.href = window.location.pathname + '?' + params.toString();
}

4. 保持复选框选中状态

渲染表单时,根据当前URL的product_tag参数,自动标记对应的复选框为选中:

// 在复选框渲染循环中添加选中判断
$tag_value = $key . ':' . $argvalue;
$is_checked = in_array($tag_value, $current_tags) ? 'checked' : '';

// 将判断结果添加到input标签
<input class="ajax-checkbox" type="checkbox" value="' . $tag_value . '" id="' . $id . '" name="product_tag[]" ' . $is_checked . ' onChange="handleFilterSubmit()" />

5. 修复清空筛选功能

原清空链接无法正确重置参数,改为直接跳转到不带筛选参数的商城页面:

// 原清空链接
<a href="#" class="deselect" onChange="this.form.submit()">Clear Filter</a>

// 修改后
<a href="<?php echo get_permalink( wc_get_page_id( 'shop' ) ); ?>" class="deselect">Clear Filter</a>

完整修改后的代码

function my_custom_tag_filter()
{
    global $wp_query;

    $return = '';

    $query_vars = $wp_query->query_vars;
    $current_tags = isset($_GET['product_tag']) ? $_GET['product_tag'] : [];

    $tags = get_terms('product_tag');
    $tagsbycategory = array();
    if (!empty($tags) && !is_wp_error($tags)) {
        foreach ($tags as $tag) {
            $tagcategorypair = explode(":", $tag->name);
            if (count($tagcategorypair) != 2) continue;
            if (!array_key_exists($tagcategorypair[0], $tagsbycategory)) {
                $tagsbycategory[$tagcategorypair[0]] = array();
            }
            $tagsbycategory[$tagcategorypair[0]][] = $tagcategorypair[1];
        }
    }

    $return .= '
        <form id="myfilter">
    ';

    $keys = array_keys($tagsbycategory);
    foreach ($keys as $key) {
        $return .= '
            <button type="button" class="collapsiblefilter">' . $key . '</button>
            <div class="filtercontent">
        ';

        $values = $tagsbycategory[$key];
        foreach ($values as $value) {
            $argvalue = str_replace(' ', '-', $value);
            $friendlyvalue = str_replace('/','',str_replace(' ', '', $value));
            $id = $key . '-' . $friendlyvalue . '-check';
            $tag_value = $key . ':' . $argvalue;
            $is_checked = in_array($tag_value, $current_tags) ? 'checked' : '';

            $return .= '
                    <div class="filtercheckdiv">
                        <label for="' . $id . '"><input class="ajax-checkbox" type="checkbox" value="' . $tag_value . '" id="' . $id . '" name="product_tag[]" ' . $is_checked . ' onChange="handleFilterSubmit()" />&nbsp;' . $value . '</label>
                    </div>
            ';
        }

        $return .= '
            </div>
        ';
    }
    if ($query_vars != null) {
        if (array_key_exists("s", $query_vars)) {
            $return .= '<input type="hidden" name="s" value="' . $query_vars["s"] . '">';
        }
        if (array_key_exists("orderby", $query_vars)) {
            $return .= '<input type="hidden" name="orderby" value="' . $query_vars["orderby"] . '">';
        }
        if (array_key_exists("order", $query_vars)) {
            $return .= '<input type="hidden" name="order" value="' . $query_vars["order"] . '">';
        }
    }

    $return .= '
        <div class="small"><a href="' . get_permalink( wc_get_page_id( 'shop' ) ) . '" class="deselect">Clear Filter</a>
        </form>
        <script>
        function handleFilterSubmit() {
            const form = document.getElementById("myfilter");
            const params = new URLSearchParams();
            
            // 收集选中的标签参数
            const productTags = form.querySelectorAll("input[name=\'product_tag[]\']:checked");
            productTags.forEach(tag => {
                params.append("product_tag[]", tag.value);
            });
            
            // 收集其他隐藏字段参数
            const hiddenFields = form.querySelectorAll("input[type=\'hidden\']");
            hiddenFields.forEach(field => {
                params.append(field.name, field.value);
            });
            
            // 跳转至筛选页面
            window.location.href = window.location.pathname + "?" + params.toString();
        }
        </script>
    ';
  
    return $return;
}
add_shortcode('my_custom_filter', 'my_custom_tag_filter');

// 注册多标签查询变量
add_filter('query_vars', 'add_multiple_product_tag_var');
function add_multiple_product_tag_var($vars) {
    $vars[] = 'product_tag';
    return $vars;
}

// 处理多标签查询逻辑
add_action('pre_get_posts', 'handle_multiple_product_tags');
function handle_multiple_product_tags($query) {
    if (!is_admin() && $query->is_main_query() && is_shop()) {
        $product_tags = isset($_GET['product_tag']) ? $_GET['product_tag'] : [];
        if (!empty($product_tags) && is_array($product_tags)) {
            // 转换为标准化标签slug
            $tag_slugs = array_map(function($tag) {
                return sanitize_title($tag);
            }, $product_tags);
            
            // 设置多标签AND匹配逻辑,如需OR匹配将'AND'改为'IN'
            $query->set('product_tag', $tag_slugs);
            $query->set('tag_operator', 'AND');
        }
    }
}

内容的提问来源于stack exchange,提问作者Venk Reddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:47:10