WooCommerce修改订单状态时如何仅触发一次指定函数?
WooCommerce订单状态切换触发短信的问题修复
问题回顾
使用woocommerce_order_status_changed钩子实现订单切换到confirmed/packing/shipped状态时发送对应语言短信,但出现两个问题:
- 切换到任意指定状态时,三个状态对应的短信都会被触发
- 计费国家非FR/BE时,仍发送法语短信
错误原因分析
- 条件逻辑写法错误:
$order->get_billing_country() == "FR" || "BE"会被PHP解析为($order->get_billing_country() == "FR") || "BE",非空字符串"BE"在布尔判断中永远为true,导致所有if条件恒成立,所有短信都会发送。 - 状态判断不够精准:使用
$order->has_status()不如直接利用钩子提供的$to_status参数,后者直接对应订单切换后的目标状态。 - 代码冗余且存在语法错误:重复的判断逻辑冗余,且
send_sms_function调用中缺少参数分隔逗号。
修复后的代码
add_action( 'woocommerce_order_status_changed', 'trigger_sms_on_new_status', 15, 4 ); function trigger_sms_on_new_status( $order_id, $from_status, $to_status, $order ) { // 定义需要触发短信的目标状态 $target_statuses = ['confirmed', 'packing', 'shipped']; // 若目标状态不在列表中,直接退出 if( !in_array( $to_status, $target_statuses ) ) return; // 获取订单相关数据 $firstname = $order->get_billing_first_name(); $phone = $order->get_billing_phone(); $shopname = get_option( 'woocommerce_email_from_name'); $country = $order->get_billing_country(); // 判断是否为法语区国家(FR/BE) $is_french_region = in_array( $country, ['FR', 'BE'] ); // 根据目标状态和地区生成对应短信内容 switch( $to_status ) { case 'confirmed': $sms_text = $is_french_region ? "Bonjour $firstname, votre commande #$order_id de $shopname..." : "Hello $firstname, your order #$order_id from $shopname..."; break; case 'packing': $sms_text = $is_french_region ? "Bonjour $firstname, votre commande #$order_id de $shopname est en cours de préparation..." : "Hello $firstname, your order #$order_id from $shopname is being prepared..."; break; case 'shipped': $sms_text = $is_french_region ? "Bonjour $firstname, votre commande #$order_id de $shopname a été expédiée..." : "Hello $firstname, your order #$order_id from $shopname has been shipped..."; break; default: $sms_text = ''; } // 确保手机号和短信内容有效,再发送短信 if( !empty($sms_text) && !empty($phone) ) { send_sms_function( $phone, $sms_text, $shopname ); $order->add_order_note( 'SMS sent with success.' ); } }
修复说明
- 精准过滤状态:通过
in_array检查目标状态,仅在切换到指定状态时执行后续逻辑,避免无关触发。 - 修正国家判断:用
in_array正确判断国家是否为FR/BE,避免逻辑运算符优先级导致的错误。 - 简化代码结构:使用switch-case统一处理不同状态的短信内容,减少冗余,提升可维护性。
- 增加有效性校验:判断手机号和短信内容非空,避免无效的短信发送调用。
- 修复语法错误:补全
send_sms_function调用中缺失的参数分隔逗号。
内容的提问来源于stack exchange,提问作者Ignatius
相关产品推荐
相关产品推荐

