WooCommerce预售场景下批量检查Processing状态订单商品库存并更新ACF字段的技术实现疑问
Fixing the "Ready to Pack" ACF Field Update for WooCommerce Pre-Orders
Let's walk through how to get your logic right for marking orders as ready to pack once all their pre-ordered items are in stock. First, let's spot the key issues in your current code:
- Wrong trigger timing: Hooking into
woocommerce_order_status_completedis too late—by the time an order hits completed status, you want it to have been marked ready to pack much earlier (while it’s still in Processing). - Incorrect inventory check logic: Your current code tries to update the field as soon as any item in the order is in stock, but we need to confirm all items are in stock first.
- Unnecessary ACF hook usage: You don’t need to hook into
acf/save_posthere—you can directly callupdate_field()once you confirm the order meets the ready-to-pack condition.
Corrected Implementation
Here's the revised code that fixes these gaps, plus adds reliable triggers to check orders when inventory changes or on a schedule:
// Main function to check Processing orders and update Ready to Pack status function auto_mark_orders_ready_to_pack() { // Get all Processing orders (cleaner, more modern parameter format) $processing_orders = wc_get_orders([ 'status' => 'processing', 'limit' => -1, // Fetch all matching orders 'type' => 'shop_order', ]); if (empty($processing_orders)) return; foreach ($processing_orders as $order) { $order_id = $order->get_id(); $all_items_in_stock = true; // Check each item in the order foreach ($order->get_items() as $item) { $product = $item->get_product(); // Safety guard: skip if product record no longer exists if (!$product) { $all_items_in_stock = false; break; } // If any item is out of stock, mark order as not ready and stop checking if (!$product->is_in_stock()) { $all_items_in_stock = false; break; } } // Update ACF field only if all items are in stock AND status hasn't been set yet if ($all_items_in_stock) { $current_status = get_field('internal_status', $order_id); if ($current_status !== 'Ready to Pack') { update_field('internal_status', 'Ready to Pack', $order_id); // Optional: Add an order note for team visibility $order->add_order_note(__('All items are now in stock. Order marked as Ready to Pack.', 'woocommerce')); } } } } // Trigger 1: Run immediately when a product's stock is updated (catches pre-order restocks) add_action('woocommerce_product_set_stock', 'auto_mark_orders_ready_to_pack'); add_action('woocommerce_variation_set_stock', 'auto_mark_orders_ready_to_pack'); // Cover variable products // Trigger 2: Hourly scheduled check as a fallback (prevents missed updates) add_action('wp', function() { if (!wp_next_scheduled('hourly_order_stock_check')) { wp_schedule_event(time(), 'hourly', 'hourly_order_stock_check'); } }); add_action('hourly_order_stock_check', 'auto_mark_orders_ready_to_pack');
Key Improvements Explained
- Accurate order readiness check: We start with a
$all_items_in_stock = trueflag, then flip it to false if any item is out of stock. This ensures we only mark orders ready when every product is available. - Dual triggers for reliability:
- Stock update hooks trigger the check instantly when a pre-order item comes in stock, so orders are marked ready as soon as possible.
- The hourly scheduled event acts as a safety net, so we don’t miss orders if a stock update hook fails to fire for any reason.
- Avoid redundant updates: We check the current value of the ACF field before updating, preventing unnecessary database writes and duplicate order notes.
- Error safeguards: We skip non-existent products to avoid PHP warnings and ensure the function runs smoothly even if product records are removed.
内容的提问来源于stack exchange,提问作者Jaime Matos
相关产品推荐
相关产品推荐

