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

折扣商品自定义过滤器失效:页面刷新而非AJAX加载

修复折扣商品过滤器的排序与AJAX加载问题

一、解决商品显示与排序错误问题

你的代码存在两个核心问题:未筛选真正有折扣的商品、排序逻辑错误(按现价排序≠按折扣高低排序)。以下是修正后的代码:

function filter_products_by_discount( $query ) {
    // 仅对前台产品归档主查询生效
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive('product') && isset( $_GET['discount_filter'] ) && ! empty( $_GET['discount_filter'] ) ) {
        
        // 筛选有折扣的商品:现价>0且小于原价
        $meta_query = $query->get('meta_query');
        $meta_query[] = array(
            'relation' => 'AND',
            array(
                'key' => '_sale_price',
                'value' => 0,
                'compare' => '>',
                'type' => 'NUMERIC'
            ),
            array(
                'key' => '_regular_price',
                'value' => '_sale_price',
                'compare' => '>',
                'type' => 'NUMERIC'
            )
        );
        $query->set('meta_query', $meta_query);

        $discount_filter = $_GET['discount_filter'];
        if ( $discount_filter === 'highest' ) {
            add_filter( 'posts_orderby', 'orderby_discount_highest' );
            // 用完即移除过滤器,避免影响其他查询
            add_filter( 'posts_orderby', function() {
                remove_filter( current_filter(), __FUNCTION__ );
                remove_filter( current_filter(), 'orderby_discount_highest' );
            });
        } elseif ( $discount_filter === 'lowest' ) {
            add_filter( 'posts_orderby', 'orderby_discount_lowest' );
            add_filter( 'posts_orderby', function() {
                remove_filter( current_filter(), __FUNCTION__ );
                remove_filter( current_filter(), 'orderby_discount_lowest' );
            });
        }
    }
}
add_action( 'pre_get_posts', 'filter_products_by_discount' );

// 按折扣率从高到低排序:(原价-现价)/原价 降序
function orderby_discount_highest( $orderby ) {
    global $wpdb;
    return "(({$wpdb->postmeta}.meta_value - (SELECT meta_value FROM {$wpdb->postmeta} AS pm WHERE pm.post_id = {$wpdb->posts}.ID AND pm.meta_key = '_sale_price')) / {$wpdb->postmeta}.meta_value) DESC";
}

// 按折扣率从低到高排序
function orderby_discount_lowest( $orderby ) {
    global $wpdb;
    return "(({$wpdb->postmeta}.meta_value - (SELECT meta_value FROM {$wpdb->postmeta} AS pm WHERE pm.post_id = {$wpdb->posts}.ID AND pm.meta_key = '_sale_price')) / {$wpdb->postmeta}.meta_value) ASC";
}

关键改动说明

  • 新增meta_query筛选逻辑,确保只显示真正有折扣的商品
  • 调整排序规则为基于「折扣率」计算,而非直接按现价排序
  • 添加过滤器自动移除逻辑,避免干扰其他页面查询

二、实现AJAX动态加载(取消页面刷新)

替换原表单提交逻辑,改用AJAX请求更新内容:

1. 修改短代码HTML结构

function discount_filter_shortcode() {
    ob_start();
    ?>
    <div class="discount-filter-wrap">
        <select id="discount-filter" name="discount_filter">
            <option value="">折扣筛选</option>
            <option value="highest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'highest' ) ? 'selected' : ''; ?>>最高折扣</option>
            <option value="lowest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'lowest' ) ? 'selected' : ''; ?>>最低折扣</option>
        </select>
    </div>
    <!-- 产品列表容器,确保ID唯一 -->
    <div id="products-list">
        <?php
        if (is_post_type_archive('product')) {
            woocommerce_product_loop_start();
            if (have_posts()) : while (have_posts()) : the_post();
                wc_get_template_part('content', 'product');
            endwhile; endif;
            woocommerce_product_loop_end();
        }
        ?>
    </div>
    <?php
    return ob_get_clean();
}
add_shortcode( 'discount_filter', 'discount_filter_shortcode' );

2. 添加AJAX处理PHP代码

// 注册AJAX动作,支持前台未登录用户访问
add_action('wp_ajax_filter_discount_products', 'filter_discount_products_ajax');
add_action('wp_ajax_nopriv_filter_discount_products', 'filter_discount_products_ajax');

function filter_discount_products_ajax() {
    $discount_filter = isset($_POST['discount_filter']) ? sanitize_text_field($_POST['discount_filter']) : '';
    $paged = isset($_POST['paged']) ? intval($_POST['paged']) : 1;

    // 构建产品查询参数
    $args = array(
        'post_type' => 'product',
        'posts_per_page' => get_option('posts_per_page'),
        'paged' => $paged,
        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key' => '_sale_price',
                'value' => 0,
                'compare' => '>',
                'type' => 'NUMERIC'
            ),
            array(
                'key' => '_regular_price',
                'value' => '_sale_price',
                'compare' => '>',
                'type' => 'NUMERIC'
            )
        )
    );

    // 设置排序规则
    if ($discount_filter === 'highest') {
        add_filter('posts_orderby', 'orderby_discount_highest');
    } elseif ($discount_filter === 'lowest') {
        add_filter('posts_orderby', 'orderby_discount_lowest');
    }

    $products_query = new WP_Query($args);

    // 输出产品HTML
    ob_start();
    if ($products_query->have_posts()) :
        woocommerce_product_loop_start();
        while ($products_query->have_posts()) : $products_query->the_post();
            wc_get_template_part('content', 'product');
        endwhile;
        woocommerce_product_loop_end();
        woocommerce_pagination();
    else :
        echo '<p>暂无折扣商品</p>';
    endif;
    wp_reset_postdata();

    // 移除过滤器
    remove_filter('posts_orderby', 'orderby_discount_highest');
    remove_filter('posts_orderby', 'orderby_discount_lowest');

    echo ob_get_clean();
    wp_die(); // 必须终止AJAX请求
}

3. 添加JavaScript逻辑

在主题目录创建js/discount-filter.js文件,内容如下:

jQuery(document).ready(function($) {
    $('#discount-filter').on('change', function() {
        var filterVal = $(this).val();
        var $productContainer = $('#products-list');
        var currentPage = $('.page-numbers.current').text() || 1;

        // 显示加载状态
        $productContainer.addClass('loading').html('<p>加载中...</p>');

        // 发送AJAX请求
        $.ajax({
            url: discountFilterAjax.ajax_url,
            type: 'POST',
            data: {
                action: 'filter_discount_products',
                discount_filter: filterVal,
                paged: currentPage
            },
            success: function(res) {
                $productContainer.removeClass('loading').html(res);
                // 更新URL参数,保持浏览器历史记录
                var newUrl = new URL(window.location.href);
                if (filterVal) {
                    newUrl.searchParams.set('discount_filter', filterVal);
                } else {
                    newUrl.searchParams.delete('discount_filter');
                }
                window.history.pushState({path: newUrl.href}, '', newUrl.href);
            },
            error: function() {
                $productContainer.removeClass('loading').html('<p>加载失败,请重试</p>');
            }
        });
    });
});

4. 注册并加载JS文件

在主题functions.php中添加:

function discount_filter_enqueue_scripts() {
    if (is_post_type_archive('product') || has_shortcode(get_post()->post_content, 'discount_filter')) {
        wp_enqueue_script('discount-filter-js', get_stylesheet_directory_uri() . '/js/discount-filter.js', array('jquery'), '1.0', true);
        wp_localize_script('discount-filter-js', 'discountFilterAjax', array(
            'ajax_url' => admin_url('admin-ajax.php')
        ));
    }
}
add_action('wp_enqueue_scripts', 'discount_filter_enqueue_scripts');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:50:53