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/>'; } } } } }
问题诊断与修复方案
核心问题
- 函数覆盖导致原有逻辑丢失:新的
TB_verify_order_content函数直接替换了旧函数,原产品18899的所有处理逻辑被完全删除 - 未定义变量报错:新函数中直接使用
$items和$user_id,但没有先获取订单对象并赋值,代码执行时会抛出错误,无法完成user_meta写入 - 缺失订单状态判断:去掉了旧代码中
$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
相关产品推荐
相关产品推荐

