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

WooCommerce订单状态变更时更新用户自定义元数据失败排查

WordPress/WooCommerce 代码失效问题:新增产品判断后user_meta无法写入

原本实现了用户购买特定订阅产品(ID:18899)后,通过更新user_meta赋予私有内容访问权限的功能,代码曾正常运行;但添加另一产品(ID:19232)的判断条件后,功能完全失效,数据库中user_meta为空,使用旧版functions.php模板时数据可正常写入,清空缓存仍无法解决问题。


之前正常运行的代码

// Order check to activate private content
add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 3 );
function TB_verify_order_content( $order_id, $old_status, $new_status ) {
    if( $new_status != 'processing' ) return;
    
    $order = wc_get_order( $order_id );
    $user_id = $order->get_user_id();
    
    // Check the product in the order
    $items = $order->get_items();
    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        
        if( $product_id == 18899 ) {

            // Check date user put in form
            $item_meta_data = $item->get_formatted_meta_data( '_', true );
            foreach( $item_meta_data as $the_data ) {
                if( $the_data->key == 'End Date' ) $enddate = $the_data->value;
            }
            
            // Check if it's a renew
            $renew = get_post_meta( $order_id, 'is_a_renew', true );
            $is_a_renew = ( isset( $renew ) && $renew == 'yes' ) ? true : false;
            
            
            if( $enddate != '' ) {
                $first_date = date( 'd/m/Y' );
                
                // Access to private content : setup at first subscription
                if ( !$is_a_renew ) {
                    $tab_access = array( 'access_begining' => time(), 
                                        'access_first_date' => $first_date, 
                                        'access_end' => '-1', 
                                        'access_end_date' => '', 
                                        'end' => $enddate                               
                                        );
                    update_user_meta( $user_id, 'BO_access_content', $tab_access );
                    
                    // End of subscription : subscription ID = Order ID of first order +1
                    $time_end = TB_end_of_subscription( $first_date, $enddate );
                    update_post_meta( $order_id+1, 'expired_date' , $time_end );
                    
                    // Date of last payment : max 25 days before 3 years
                    $time_end = DateTime::createFromFormat( 'd/m/Y', $enddate );
                    $time_end->modify( '- 25 days' );
                    $time_thirtysix = TB_end_of_subscription( $first_date, $enddate, 36 ); // 36th subscription month
                    $tab_payments = array( 'date_dp' => date( 'd/m/Y', $time_end->getTimestamp() ),
                                            'time_adp' => $time_thirtysix
                                            );
                    update_post_meta( $order_id, 'last_payment' , $tab_payments );
                }
                
                // Data to check box and next box
                $num_box = TB_calculate_box( $first_date, $enddate );
                $next_month = date( 'd/m/Y', mktime(0, 0, 0, date('m')+1, 5, date('Y') ) );
                
                $tab_box = array( array( 'box' => $num_box, 'date' => $first_date ) );
                if( $num_box < 36 ) $tab_box[] = array( 'box' => $num_box+1, 'date' => $next_month );

                update_post_meta( $order_id, 'BO_envoi_box', $tab_box );
            }
        }
    }
}

// Evaluating subscription month and verify end of subscription
function TB_max_month_autorized( $tab_param ) {
    $return = -1;   
    
    // Ongoing month
    $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['end'] );
    
    // If subscription stops, changes content access autorization 
    if( $tab_param['access_end'] != '-1' && $tab_param['access_end_date'] != '' ) {
        $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['acces_end_date'] );
    }
    
    return $return;
}

// Add content in tab "My content"
add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
function TB_add_content() {
    // Getting user data
    $current_user = wp_get_current_user();
    $access_autorized = false;
    $month_user = -1;
    
    if ( $current_user->ID > 0 ) {
                    
        $tab_access = get_user_meta( $current_user->ID, 'BO_access_content', true );
        
        // Calculation of subscription month and number of box
        if( isset( $tab_access ) && is_array( $tab_access ) && $tab_access['end'] != '' ) {
            $month_user = TB_max_month_autorized( $tab_access );
        } 
                            
        // Subscription ongoing, list of accessible content
        if( $month_user > 0 ) {
            $query = new WP_Query( array(
                'post_type'     => 'page',
                'meta_key'      => '_wp_page_template',
                'meta_value'    => 'templates/template-private_page.php',
                'order'         => 'DESC',
                'orderby'       => 'menu_order',
                'meta_key'      => 'access_month',
                'meta_value'    => $month_user,
                'meta_compare'  => '<=',
                'posts_per_page' => -1,
            ) );
            
            if ( $query->have_posts() ) {
                while ( $query->have_posts() ) : $query->the_post();
                    $menu_order = get_post_field('menu_order', get_the_ID());

                    if ($menu_order < 100) {
                        echo '<a class="button content_link" target="_blank" title="'.get_the_title().'" href="'.get_the_permalink().'">';
                            the_title();
                        echo '</a>';
                    
                        echo '<br/>';
                    }
                endwhile; // end of the loop.
            } 
            wp_reset_query();
        }
    }
}

当前使用的失效代码

// Order check to activate private content
add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 3 );
function TB_verify_order_content( $order_id, $old_status, $new_status ) {
   // Check New product in the order
    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        
        if( $product_id == 19232 ) {
            update_user_meta( $user_id, 'BO_access_special_content', true );
        }
    }
}
    

// Add content in tab "My content"
add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
function TB_add_content() {

    // Check if user bought product and Display Special Content
    $current_user = wp_get_current_user();
    if ( $current_user->ID > 0 ) {
        $user_orders = wc_get_orders( array( 'customer_id' => $current_user->ID ) );
        foreach ( $user_orders as $user_order ) {
            if ( get_post_meta( $user_order->get_id(), 'BO_access_special_content', true ) ) {                
                $article_ids = array(19232);
                foreach ($article_ids as $article_id) {
                    echo '<a class="button content_link" target="_blank" title="'.get_the_title($article_id).'" href="'.get_permalink($article_id).'">';
                    echo get_the_title($article_id);
                    echo '</a><br/>';
                }
            }
        }
    }
}

问题诊断与修复方案

核心问题

  1. 函数覆盖导致原有逻辑丢失:新的TB_verify_order_content函数直接替换了旧函数,原产品18899的所有处理逻辑被完全删除
  2. 未定义变量报错:新函数中直接使用$items和$user_id,但没有先获取订单对象并赋值,代码执行时会抛出错误,无法完成user_meta写入
  3. 缺失订单状态判断:去掉了旧代码中$new_status != 'processing'的判断,导致订单状态不符合时也会触发逻辑,容易引发异常

修复后的完整代码

将两个产品的处理逻辑合并,保留原有功能的同时新增19232产品的判断:

// Order check to activate private content
add_action( 'woocommerce_order_status_changed', 'TB_verify_order_content', 10, 3 );
function TB_verify_order_content( $order_id, $old_status, $new_status ) {
    // 仅在订单状态变为processing时执行
    if( $new_status != 'processing' ) return;
    
    $order = wc_get_order( $order_id );
    $user_id = $order->get_user_id();
    
    // 跳过未登录用户的订单
    if ( empty($user_id) ) return;
    
    $items = $order->get_items();
    foreach ( $items as $item ) {
        $product_id = $item->get_product_id();
        
        // 处理原产品18899的逻辑
        if( $product_id == 18899 ) {
            // Check date user put in form
            $item_meta_data = $item->get_formatted_meta_data( '_', true );
            $enddate = '';
            foreach( $item_meta_data as $the_data ) {
                if( $the_data->key == 'End Date' ) $enddate = $the_data->value;
            }
            
            // Check if it's a renew
            $renew = get_post_meta( $order_id, 'is_a_renew', true );
            $is_a_renew = ( isset( $renew ) && $renew == 'yes' ) ? true : false;
            
            if( $enddate != '' ) {
                $first_date = date( 'd/m/Y' );
                
                // Access to private content : setup at first subscription
                if ( !$is_a_renew ) {
                    $tab_access = array( 
                        'access_begining' => time(), 
                        'access_first_date' => $first_date, 
                        'access_end' => '-1', 
                        'access_end_date' => '', 
                        'end' => $enddate                               
                    );
                    update_user_meta( $user_id, 'BO_access_content', $tab_access );
                    
                    // End of subscription : subscription ID = Order ID of first order +1
                    if ( function_exists('TB_end_of_subscription') ) {
                        $time_end = TB_end_of_subscription( $first_date, $enddate );
                        update_post_meta( $order_id+1, 'expired_date' , $time_end );
                    }
                    
                    // Date of last payment : max 25 days before 3 years
                    $time_end = DateTime::createFromFormat( 'd/m/Y', $enddate );
                    if ( $time_end ) {
                        $time_end->modify( '- 25 days' );
                        if ( function_exists('TB_end_of_subscription') ) {
                            $time_thirtysix = TB_end_of_subscription( $first_date, $enddate, 36 ); // 36th subscription month
                            $tab_payments = array( 
                                'date_dp' => date( 'd/m/Y', $time_end->getTimestamp() ),
                                'time_adp' => $time_thirtysix
                            );
                            update_post_meta( $order_id, 'last_payment' , $tab_payments );
                        }
                    }
                }
                
                // Data to check box and next box
                if ( function_exists('TB_calculate_box') ) {
                    $num_box = TB_calculate_box( $first_date, $enddate );
                    $next_month = date( 'd/m/Y', mktime(0, 0, 0, date('m')+1, 5, date('Y') ) );
                    
                    $tab_box = array( array( 'box' => $num_box, 'date' => $first_date ) );
                    if( $num_box < 36 ) $tab_box[] = array( 'box' => $num_box+1, 'date' => $next_month );

                    update_post_meta( $order_id, 'BO_envoi_box', $tab_box );
                }
            }
        }
        
        // 处理新增产品19232的逻辑
        if( $product_id == 19232 ) {
            update_user_meta( $user_id, 'BO_access_special_content', true );
        }
    }
}

// Evaluating subscription month and verify end of subscription
function TB_max_month_autorized( $tab_param ) {
    $return = -1;   
    
    // Ongoing month
    if ( function_exists('TB_calculate_month') ) {
        $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['end'] );
    }
    
    // If subscription stops, changes content access autorization 
    if( isset($tab_param['access_end']) && $tab_param['access_end'] != '-1' && isset($tab_param['access_end_date']) && $tab_param['access_end_date'] != '' ) {
        if ( function_exists('TB_calculate_month') ) {
            $return = TB_calculate_month( $tab_param['access_first_date'], $tab_param['access_end_date'] );
        }
    }
    
    return $return;
}

// Add content in tab "My content"
add_action( 'woocommerce_account_downloads_endpoint', 'TB_add_content' );
function TB_add_content() {
    // Getting user data
    $current_user = wp_get_current_user();
    $access_autorized = false;
    $month_user = -1;
    
    if ( $current_user->ID > 0 ) {
        // 显示原私有内容
        $tab_access = get_user_meta( $current_user->ID, 'BO_access_content', true );
        
        // Calculation of subscription month and number of box
        if( isset( $tab_access ) && is_array( $tab_access ) && $tab_access['end'] != '' ) {
            $month_user = TB_max_month_autorized( $tab_access );
        } 
                            
        // Subscription ongoing, list of accessible content
        if( $month_user > 0 ) {
            $query = new WP_Query( array(
                'post_type'     => 'page',
                'meta_key'      => '_wp_page_template',
                'meta_value'    => 'templates/template-private_page.php',
                'order'         => 'DESC',
                'orderby'       => 'menu_order',
                'meta_key'      => 'access_month',
                'meta_value'    => $month_user,
                'meta_compare'  => '<=',
                'posts_per_page' => -1,
            ) );
            
            if ( $query->have_posts() ) {
                while ( $query->have_posts() ) : $query->the_post();
                    $menu_order = get_post_field('menu_order', get_the_ID());

                    if ($menu_order < 100) {
                        echo '<a class="button content_link" target="_blank" title="'.get_the_title().'" href="'.get_the_permalink().'">';
                            the_title();
                        echo '</a>';
                    
                        echo '<br/>';
                    }
                endwhile; // end of the loop.
            } 
            wp_reset_query();
        }
        
        // 显示新增的特殊内容
        $has_special_access = get_user_meta( $current_user->ID, 'BO_access_special_content', true );
        if ( $has_special_access ) {                
            $article_ids = array(19232);
            foreach ($article_ids as $article_id) {
                echo '<a class="button content_link" target="_blank" title="'.get_the_title($article_id).'" href="'.get_permalink($article_id).'">';
                echo get_the_title($article_id);
                echo '</a><br/>';
            }
        }
    }
}

修复说明

  • 合并了两个产品的处理逻辑,保留原18899的所有功能
  • 修复了未定义变量的问题,先获取订单对象和用户ID
  • 增加了函数存在性判断(function_exists),避免依赖函数缺失导致报错
  • 优化了特殊内容的判断逻辑,直接读取user_meta而非遍历所有订单,提升性能
  • 保留了订单状态判断,确保仅在合适时机执行逻辑

内容的提问来源于stack exchange,提问作者Tony Bazolas37

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:35:54