You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:27:02