WooCommerce后台修改订单后获取新数据的后置钩子咨询
Hey there! I totally get the frustration with those WooCommerce order hooks—let's break down the best solutions for your use case where you need access to the saved, updated order data (like addresses or custom meta fields) after an edit in the backend.
1. Use woocommerce_after_save_order (Recommended)
This hook was introduced specifically for scenarios where you need to run code after an order has been fully saved—including all meta data and address updates. Unlike woocommerce_process_shop_order_meta (which fires before saves) or save_post_shop_order (where meta is already updated but you can't easily grab old values), this hook gives you direct access to the fresh, updated WC_Order object.
Example Code:
add_action( 'woocommerce_after_save_order', 'my_post_order_save_action', 10, 2 ); function my_post_order_save_action( $order_id, $order ) { // Get updated billing address details $new_billing_street = $order->get_billing_address_1(); $new_billing_city = $order->get_billing_city(); // Get updated custom meta field $new_custom_meta = $order->get_meta( '_my_custom_order_meta' ); // Do your work here—log changes, sync to a CRM, trigger notifications, etc. error_log( "Order {$order_id} updated: New billing address is {$new_billing_street}, {$new_billing_city}" ); }
2. Comparing Old vs. New Data (If You Need to Track Changes)
If you need to compare the original order data with the updated version (e.g., to log exactly what changed), you can pair woocommerce_before_save_order (to capture old data) with woocommerce_after_save_order (to compare it against the new data).
Example with Transients (Avoids Concurrency Issues):
Using WordPress transients is safer than global variables for multi-user environments, as it ties old data directly to the order ID:
// Capture old order data right before the save happens add_action( 'woocommerce_before_save_order', 'capture_old_order_data', 10, 2 ); function capture_old_order_data( $order_id, $order ) { $old_order_data = array( 'billing_address' => $order->get_billing_address_1(), 'custom_meta' => $order->get_meta( '_my_custom_order_meta' ) ); // Store old data temporarily (5-minute expiration is more than enough for the save process) wp_transient_set( "old_order_{$order_id}", $old_order_data, 300 ); } // Compare old vs new data after the order is saved add_action( 'woocommerce_after_save_order', 'compare_order_changes', 10, 2 ); function compare_order_changes( $order_id, $order ) { $old_data = wp_transient_get( "old_order_{$order_id}" ); if ( ! $old_data ) return; $new_billing_address = $order->get_billing_address_1(); $new_custom_meta = $order->get_meta( '_my_custom_order_meta' ); // Check if billing address changed if ( $old_data['billing_address'] !== $new_billing_address ) { error_log( "Order {$order_id}: Billing address changed from '{$old_data['billing_address']}' to '{$new_billing_address}'" ); // Run your custom action here (e.g., notify a warehouse) } // Check if custom meta changed if ( $old_data['custom_meta'] !== $new_custom_meta ) { error_log( "Order {$order_id}: Custom meta changed from '{$old_data['custom_meta']}' to '{$new_custom_meta}'" ); // Run your custom action here } // Clean up the transient so it doesn't linger in the database wp_transient_delete( "old_order_{$order_id}" ); }
Why Your Previous Hooks Didn't Work
woocommerce_process_shop_order_meta: Fires before the order and its meta are saved, so new values aren't available yet.save_post_shop_order: A WordPress core hook that fires after the post is saved, but WooCommerce updates meta data before this hook runs—so you can't access the original values to compare changes.
The woocommerce_after_save_order hook solves both these issues by firing at the exact right point in the order save lifecycle, designed specifically for WooCommerce orders.
内容的提问来源于stack exchange,提问作者Liam McArthur

