WooCommerce HPOS后台手动创建订单时强制设置账单邮编与商品
问题描述
我正在使用搭载HPOS的最新版WooCommerce。为避免后台手动创建的订单出现无商品、无账单邮编的情况,我编写了一个函数,意图在账单邮编为空或未添加商品时阻止订单创建。以下是我的代码尝试:
// During Order creation in the admin area - force to set at least one procduct and billing postalcode to avoid issues on the order overview screen and more function avoid_orders_wout_b_postalcode_a_wout_products_9sadfM324($post_id, $post) { // Get the order object $order = wc_get_order($post_id); // Check if the order has products $items = $order->get_items(); if (empty($items)) { // Add an error message to WooCommerce admin notices WC_Admin_Notices::add_custom_notice('no_products_added_error', 'ERROR YCNC0084 - ' . __('You cannot create an order without adding any products', 'nm-framework')); // Redirect to the edit order screen wp_redirect(admin_url('post.php?post=' . $post_id . '&action=edit')); exit; } // Check for postal code in billing and shipping address $billing_postcode = $order->get_billing_postcode(); // $shipping_postcode = $order->get_shipping_postcode(); // if (empty($billing_postcode) && empty($shipping_postcode)) { if ( empty($billing_postcode) ) { // Add an error message to WooCommerce admin notices WC_Admin_Notices::add_custom_notice('no_billing_postalcode_error', 'ERROR YCNC0024 - ' . __('You cannot create an order without a billing postal code', 'nm-framework')); // Redirect to the edit order screen wp_redirect(admin_url('post.php?post=' . $post_id . '&action=edit')); exit; } } add_action('woocommerce_process_shop_order_meta', 'avoid_orders_wout_b_postalcode_a_wout_products_9sadfM324', 99, 2); // must higher then 40 according to stackoverflow answer
目前问题是:仅填写账单邮编就能保存/创建订单(即未添加商品但填了邮编时,订单仍能被创建),实际需要同时满足有商品、有账单邮编两个条件才能创建订单,请问该如何修复?
修复方案
问题根源
- 钩子不兼容HPOS:启用HPOS后,订单不再作为WordPress的
post类型存储,原钩子woocommerce_process_shop_order_meta仅针对传统post类型订单生效,无法触发HPOS订单的验证逻辑。 - 错误处理逻辑缺陷:原代码遇到单个错误就直接
exit,无法同时验证两个条件,且wp_redirect在HPOS场景下可能无法正确拦截订单创建。
修正后的代码
// 后台创建/编辑订单时,强制验证商品和账单邮编 function validate_admin_order_requirements($order) { $errors = []; // 检查订单是否有商品 if (empty($order->get_items())) { $errors[] = 'ERROR YCNC0084 - ' . __('You cannot create an order without adding any products', 'nm-framework'); } // 检查账单邮编是否为空 if (empty($order->get_billing_postcode())) { $errors[] = 'ERROR YCNC0024 - ' . __('You cannot create an order without a billing postal code', 'nm-framework'); } // 如果存在错误,阻止订单保存并显示通知 if (!empty($errors)) { foreach ($errors as $error_msg) { WC_Admin_Notices::add_custom_notice('order_validation_error', $error_msg); } // 通过抛出异常阻止订单保存(HPOS兼容方式) throw new Exception(implode(' ', $errors)); } } add_action('woocommerce_admin_process_order', 'validate_admin_order_requirements', 10, 1);
关键说明
- HPOS兼容钩子:使用
woocommerce_admin_process_order钩子,该钩子是WooCommerce为HPOS场景提供的官方订单处理钩子,参数直接传入$order对象,无需通过post_id获取。 - 统一错误收集:先收集所有不符合条件的错误,再一次性抛出,用户能同时看到所有未满足的要求。
- 异常拦截保存:通过抛出
Exception来阻止订单保存,这是HPOS下可靠的拦截方式,替代原代码的wp_redirect+exit,避免订单被提前创建。
内容的提问来源于stack exchange,提问作者eva last
相关产品推荐
相关产品推荐

