WooCommerce钩子更新订单状态触发PHP通知问题求助
WooCommerce订单状态更新触发PHP通知的排查与解决
错误提示
Notice: Function ID was called incorrectly. Order properties should not be accessed directly. auto_complete_specific_product_order, WC_Order->update_status, WC_Order->save, WC_Order->status_transition, do_action('woocommerce_order_status_completed'), WP_Ho in C:\Websites\mysite\www\wp-includes\functions.php on line 5865
触发问题的代码
// Hook the function to the order status change specifically for "completed" add_action('woocommerce_order_status_completed', 'transfer_product_status_complete', 10, 2); function transfer_product_status_complete($order_id) { global $wpdb; // Retrieve the order $order = wc_get_order($order_id); // Check if the desired product is in the order $found = false; foreach ($order->get_items() as $item) { $product_id = $item->get_product_id(); if ($product_id === 825 || $product_id === 885) { $found = true; break; } } // Execute the code only if the desired product is found if ($found) { // Retrieve the order user ID $order = wc_get_order($order_id); $new_owner_id = $order->get_user_id(); // Retrieve and update custom fields when order becomes complete $serial_number_transfer = get_post_meta($order_id, 'serial_to_be_transferred', true); if (metadata_exists('post', $order_id, 'serial_to_be_transferred')) { // save the serial number update_post_meta($order_id, 'hash_data', $serial_number_transfer); // remove the serial from the custom field of the old owner $orders = wc_get_orders(array( 'customer' => $current_owner_id, 'limit' => -1, // Retrieve all orders )); foreach ($orders as $order) { $order_id_sender = $order->ID; $serial_numbers = get_post_meta($order_id_sender, 'hash_data'); $new_meta_value = str_replace($serial_number_transfer, '', $serial_numbers[0]); // Update the post meta with the new value update_post_meta($order_id_sender, 'hash_data', $new_meta_value); } // delete the custom field called serial_to_be_transferred delete_post_meta($order_id, 'serial_to_be_transferred'); } } }
问题排查与解决方案
1. 直接访问WC_Order属性导致通知
错误提示明确指出不能直接访问Order属性,问题出在这段代码:
$order_id_sender = $order->ID;
WooCommerce 3.0+版本要求用官方getter方法获取订单ID,替换为:
$order_id_sender = $order->get_id();
2. 未定义变量$current_owner_id
代码中用$current_owner_id作为查询条件,但该变量从未定义,会导致查询失败。需补充定义,比如从自定义字段获取旧所有者ID:
// 根据实际业务逻辑调整旧所有者ID的来源 $current_owner_id = get_post_meta($order_id, 'old_owner_id', true);
3. 冗余的订单对象获取
代码重复执行$order = wc_get_order($order_id);,删除重复调用,复用已获取的订单对象即可。
修正后的完整代码
// Hook the function to the order status change specifically for "completed" add_action('woocommerce_order_status_completed', 'transfer_product_status_complete', 10, 2); function transfer_product_status_complete($order_id) { global $wpdb; // Retrieve the order $order = wc_get_order($order_id); // Check if the desired product is in the order $found = false; foreach ($order->get_items() as $item) { $product_id = $item->get_product_id(); if ($product_id === 825 || $product_id === 885) { $found = true; break; } } // Execute the code only if the desired product is found if ($found) { // Retrieve the order user ID $new_owner_id = $order->get_user_id(); // Retrieve and update custom fields when order becomes complete $serial_number_transfer = get_post_meta($order_id, 'serial_to_be_transferred', true); if (metadata_exists('post', $order_id, 'serial_to_be_transferred')) { // save the serial number update_post_meta($order_id, 'hash_data', $serial_number_transfer); // 补充定义旧所有者ID,根据实际业务逻辑调整来源 $current_owner_id = get_post_meta($order_id, 'old_owner_id', true); // remove the serial from the custom field of the old owner $orders = wc_get_orders(array( 'customer' => $current_owner_id, 'limit' => -1, // Retrieve all orders )); foreach ($orders as $order) { $order_id_sender = $order->get_id(); $serial_numbers = get_post_meta($order_id_sender, 'hash_data'); if (!empty($serial_numbers[0])) { $new_meta_value = str_replace($serial_number_transfer, '', $serial_numbers[0]); // Update the post meta with the new value update_post_meta($order_id_sender, 'hash_data', $new_meta_value); } } // delete the custom field called serial_to_be_transferred delete_post_meta($order_id, 'serial_to_be_transferred'); } } }
额外优化建议
- 增加空值判断:对
$serial_numbers[0]做非空校验,避免str_replace报错 - 批量操作优化:若旧所有者订单数量多,限制查询范围或用批量更新提升性能
- 日志记录:添加
error_log()记录关键操作,方便后续排查
内容的提问来源于stack exchange,提问作者matead
相关产品推荐
相关产品推荐

