WooCommerce启用自定义meta显示过滤器后订单项自定义元数据无法删除
问题核心诱因
woocommerce_order_item_get_formatted_meta_data 过滤器的返回值并非仅用于前端展示场景:WooCommerce内部在订单状态变更、订单项数据持久化的全流程中都会调用该方法,且默认调用时会开启hide_prefix参数(隐藏所有以下划线开头的私有元数据),后续会将返回的格式化元数据列表同步回订单项的真实元数据存储。
你在过滤器中新增了key = 'test'的公开元数据项,当取消订单触发库存恢复的流程时:
- WooCommerce内部先调用
get_formatted_meta_data(),返回的列表中没有你添加的私有元数据_test_data(被隐藏),仅包含原有公开元数据+你新增的test项 - 内部逻辑会将该列表同步到订单项的待保存元数据中,这一步就已经将原来的
_test_data从元数据列表中移除,同时新增了test项 - 等流程走到你写的库存恢复钩子时,
_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
相关产品推荐
相关产品推荐

