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

如何解决WooCommerce Analytics自定义Weight列无法排序的问题?

WooCommerce Analytics分类报表自定义列排序问题解决

问题背景

在WooCommerce Analytics的分类报表中添加了自定义「Weight」列,用于展示对应分类下售出商品的总重量。采用woocommerce_rest_prepare_report_categories钩子编写PHP代码,woocommerce_admin_report_table钩子编写JS代码后,列显示正常,但设置isSortable: true后点击排序触发400错误,提示orderby参数不在允许的枚举值列表中,需要补充处理orderby参数的逻辑。

现有代码

PHP代码

add_filter( 'woocommerce_rest_prepare_report_categories', 'add_category_weight_in_rest', 10, 3 );
function add_category_weight_in_rest ($response, $report, $request ){
    
    $data = $response->get_data();
    $category_id = $data['category_id'];

    $params = $request->get_params();
    $after = $params['after'];
    $before = $params['before'];

    $data['category_weight'] = get_ordered_weight_by_category($category_id, $after, $before);
    $response->set_data($data);

    return $response;
}

JS代码

function addWeightToCategories( reportTableData ) {

    const { endpoint, items } = reportTableData;
    if ( 'categories' !== endpoint ) {
        return reportTableData;
    }
  
    reportTableData.headers = [
        ...reportTableData.headers,
        {
            label: 'Weight',
            key: 'category_weight',
            isNumeric: true,
            //isSortable: true
        },
    ];
    reportTableData.rows = reportTableData.rows.map( ( row, index ) => {

        const item = items.data[ index ];
        const newRow = [
            ...row,
            {
                display: item.category_weight,
                value: item.category_weight,
            },
        ];
        return newRow;
    } );
  
    return reportTableData;
}
wp.hooks.addFilter( 'woocommerce_admin_report_table', 'mysupershop', addWeightToCategories );

错误信息

原始错误:

{"code":"rest_invalid_param","message":"Invalid parameters : « orderby »","data":{"status":400,"params":{"orderby":"orderby is not one of category_id, items_sold, net_revenue, orders_count, products_count, et category."},"details":{"orderby":{"code":"rest_not_in_enum","message":"orderby is not one of category_id, items_sold, net_revenue, orders_count, products_count, et category.","data":null}}}}

翻译后:

{"code":"rest_invalid_param","message":"无效参数:« orderby »","data":{"status":400,"params":{"orderby":"orderby 不属于 category_id, items_sold, net_revenue, orders_count, products_count, category 中的任何一个。"},"details":{"orderby":{"code":"rest_not_in_enum","message":"orderby 不属于 category_id, items_sold, net_revenue, orders_count, products_count, category 中的任何一个。","data":null}}}}

解决方案

要解决排序问题,需完成两个核心操作:允许orderby参数包含自定义字段,以及实现该字段的排序逻辑。

1. 扩展orderby参数的合法值

添加过滤器让REST API接受category_weight作为合法的排序字段:

add_filter( 'woocommerce_rest_report_categories_collection_params', 'add_category_weight_orderby_param', 10, 1 );
function add_category_weight_orderby_param( $params ) {
    if ( isset( $params['orderby']['enum'] ) ) {
        $params['orderby']['enum'][] = 'category_weight';
    }
    return $params;
}

2. 实现自定义字段的排序逻辑

由于category_weight是动态计算的字段,无法直接通过数据库查询排序,需先获取所有分类数据、计算重量后再排序:

add_filter( 'woocommerce_rest_report_categories_query', 'sort_categories_by_weight', 10, 2 );
function sort_categories_by_weight( $query_args, $request ) {
    $orderby = $request->get_param( 'orderby' );
    $order = $request->get_param( 'order' ) ?: 'asc';

    if ( 'category_weight' === $orderby ) {
        // 获取原始报表数据
        $report = new WC_Admin_Report_Categories();
        $categories_data = $report->get_report_data( $query_args );
        
        // 为每个分类计算总重量
        foreach ( $categories_data->data as &$category ) {
            $category->category_weight = get_ordered_weight_by_category(
                $category->category_id,
                $query_args['after'],
                $query_args['before']
            );
        }
        
        // 根据重量排序
        usort( $categories_data->data, function( $a, $b ) use ( $order ) {
            if ( $a->category_weight == $b->category_weight ) {
                return 0;
            }
            return ( 'asc' === $order ) 
                ? ( $a->category_weight < $b->category_weight ? -1 : 1 )
                : ( $a->category_weight > $b->category_weight ? -1 : 1 );
        } );
        
        // 替换原始查询结果
        add_filter( 'woocommerce_admin_report_get_report_data', function( $data ) use ( $categories_data ) {
            return $categories_data;
        }, 10, 2 );
    }

    return $query_args;
}

3. 启用JS排序设置

取消JS代码中isSortable: true的注释:

{
    label: 'Weight',
    key: 'category_weight',
    isNumeric: true,
    isSortable: true
},

注意事项

确保get_ordered_weight_by_category函数能正确计算指定时间范围内,对应分类下所有售出商品的总重量,否则排序结果会不准确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 14:10:57