WooCommerce自定义代码导致更新订单状态时网站崩溃
问题:WordPress后台重发优惠券订单通知时触发严重错误
在WordPress后台操作订单(如通过「订单操作」→选择操作→重新发送订单通知)时,网站出现严重错误,该问题仅在使用优惠券的特定订单上触发。
错误信息
An error of type E_ERROR was caused in line 21 of the file /usr/www/users/africgebks/wp-content/themes/woodmart-child/functions.php. Error message: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given in /usr/www/users/africgebks/wp-content/themes/woodmart-child/functions.php:21 Stack trace: #0 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(310): display_applied_coupons(Object(Automattic\WooCommerce\Admin\Overrides\Order), true, false, Object(WC_Email_New_Order)) #1 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters('', Array) #2 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #3 /usr/www/users/africgebks/wp-content/plugins/woocommerce/templates/emails/admin-new-order.php(35): do_action('woocommerce_ema...', Object(Automattic\WooCommerce\Admin\Overrides\Order), true, false, Object(WC_Email_New_Order)) #4 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/wc-core-functions.php(345): include('/usr/www/users/...') #5 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/wc-core-functions.php(364): wc_get_template('emails/admin-ne...', Array, '', '') #6 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email-new-order.php(134): wc_get_template_html('emails/admin-ne...', Array) #7 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email.php(581): WC_Email_New_Order->get_content_html() #8 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/emails/class-wc-email-new-order.php(111): WC_Email->get_content() #9 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php(156): WC_Email_New_Order->trigger(14992, Object(Automattic\WooCommerce\Admin\Overrides\Order), true) #10 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(310): WC_Meta_Box_Order_Actions::save(14992, Object(WP_Post)) #11 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters(NULL, Array) #12 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #13 /usr/www/users/africgebks/wp-content/plugins/woocommerce/includes/admin/class-wc-admin-meta-boxes.php(258): do_action('woocommerce_pro...', 14992, Object(WP_Post)) #14 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(312): WC_Admin_Meta_Boxes->save_meta_boxes(14992, Object(WP_Post)) #15 /usr/www/users/africgebks/wp-includes/class-wp-hook.php(334): WP_Hook->apply_filters('', Array) #16 /usr/www/users/africgebks/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #17 /usr/www/users/africgebks/wp-includes/post.php(4751): do_action('save_post', 14992, Object(WP_Post), true) #18 /usr/www/users/africgebks/wp-includes/post.php(4853): wp_insert_post(Array, false, true) #19 /usr/www/users/africgebks/wp-admin/includes/post.php(445): wp_update_post(Array) #20 /usr/www/users/africgebks/wp-admin/post.php(227): edit_post() #21 {main} thrown
问题根源
错误来自Woodmart子主题functions.php中的自定义优惠券显示代码,原代码如下:
// The email function hooked that display the text add_action( 'woocommerce_email_order_details', 'display_applied_coupons', 10, 4 ); function display_applied_coupons( $order, $sent_to_admin, $plain_text, $email ) { // Only for admins and when there at least 1 coupon in the order if ( ! $sent_to_admin && count($order->get_items('coupon') ) == 0 ) return; foreach( $order->get_items('coupon') as $coupon ){ $coupon_codes[] = $coupon->get_code(); } // For one coupon if( count($coupon_codes) == 1 ){ $coupon_code = reset($coupon_codes); echo '<p>'.__( 'Coupon Used: ').$coupon_code.'<p>'; } // For multiple coupons else { $coupon_codes = implode( ', ', $coupon_codes); echo '<p>'.__( 'Coupons Used: ').$coupon_codes.'<p>'; } }
错误分析
- 条件判断逻辑错误:原代码仅在「非管理员且无优惠券」时返回,但管理员操作无优惠券订单时,代码会继续执行,此时
$order->get_items('coupon')可能返回null或空,导致$coupon_codes未初始化。 - PHP8.1类型严格检查:PHP8.1对
count()函数的参数要求严格,必须是可计数类型(数组/Countable对象),未定义的$coupon_codes或null会触发TypeError。 - 未处理
get_items返回值:$order->get_items('coupon')在某些情况下可能返回null,而非空数组,直接遍历会导致后续变量未定义。
修正后的代码
// 在订单邮件中显示使用的优惠券 add_action( 'woocommerce_email_order_details', 'display_applied_coupons', 10, 4 ); function display_applied_coupons( $order, $sent_to_admin, $plain_text, $email ) { // 获取订单中的优惠券项目,确保是可计数类型 $coupon_items = $order->get_items('coupon'); $coupon_items = is_countable($coupon_items) ? $coupon_items : []; // 仅针对管理员,且订单存在优惠券时执行 if ( !$sent_to_admin || count($coupon_items) === 0 ) { return; } $coupon_codes = []; foreach( $coupon_items as $coupon ){ $coupon_codes[] = $coupon->get_code(); } // 显示单个优惠券 if( count($coupon_codes) === 1 ){ $coupon_code = reset($coupon_codes); echo '<p>'.__( '使用优惠券: ').$coupon_code.'</p>'; } // 显示多个优惠券 else { $coupon_codes_str = implode( ', ', $coupon_codes); echo '<p>'.__( '使用优惠券: ').$coupon_codes_str.'</p>'; } }
环境信息
- WordPress版本:6.3
- 启用主题:Woodmart Child(1.0.0)
- PHP版本:8.1.22
内容的提问来源于stack exchange,提问作者DylanG
相关产品推荐
相关产品推荐

