You need to enable JavaScript to run this app. WooCommerce启用自定义meta显示过滤器后订单项自定义元数据无法删除
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce启用自定义meta显示过滤器后订单项自定义元数据无法删除

问题核心诱因

woocommerce_order_item_get_formatted_meta_data 过滤器的返回值并非仅用于前端展示场景:WooCommerce内部在订单状态变更、订单项数据持久化的全流程中都会调用该方法,且默认调用时会开启hide_prefix参数(隐藏所有以下划线开头的私有元数据),后续会将返回的格式化元数据列表同步回订单项的真实元数据存储。

你在过滤器中新增了key = 'test'的公开元数据项,当取消订单触发库存恢复的流程时:

  1. WooCommerce内部先调用get_formatted_meta_data(),返回的列表中没有你添加的私有元数据_test_data(被隐藏),仅包含原有公开元数据+你新增的test项
  2. 内部逻辑会将该列表同步到订单项的待保存元数据中,这一步就已经将原来的_test_data从元数据列表中移除,同时新增了test项
  3. 等流程走到你写的库存恢复钩子时,_test_data已经被提前移除,你执行删除操作自然无法找到对应元数据,最终调用save()时反而将test项正式写入数据库,就出现了你日志中看到的元数据被篡改的现象。

解决方案

在库存恢复的钩子执行前先临时移除woocommerce_order_item_get_formatted_meta_data过滤器,处理完元数据删除逻辑后再恢复即可,修改后的代码如下:

add_action( 'woocommerce_restore_order_stock', 'woocommerce_restore_order_stock_action', 10, 1 );
function woocommerce_restore_order_stock_action( $order ): void {
    // 临时移除格式化元数据过滤器,避免后台保存流程被干扰
    remove_filter( 'woocommerce_order_item_get_formatted_meta_data', 'filter_woocommerce_order_item_get_formatted_meta_data', 10 );
    
    $order_items = $order->get_items();
    if ( empty( $order_items ) ) {
        // 恢复过滤器后再返回
        add_filter( 'woocommerce_order_item_get_formatted_meta_data', 'filter_woocommerce_order_item_get_formatted_meta_data', 10, 2 );
        return;
    }

    foreach ( $order_items as $order_item ) {
        if ( ! is_object( $order_item ) ) {
            continue;
        }
        $order_item->delete_meta_data( '_test_data' );
        $order_item->save();
    }

    // 处理完成后恢复过滤器,不影响前端展示逻辑
    add_filter( 'woocommerce_order_item_get_formatted_meta_data', 'filter_woocommerce_order_item_get_formatted_meta_data', 10, 2 );
}

如果需要更通用的规避方案,也可以在原过滤器中增加上下文判断,仅在前端/邮件等展示场景下新增自定义元数据项,避免后台操作流程被干扰。

内容的提问来源于stack exchange,提问作者Mr. Jo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 16:54:01