WooCommerce 5.6+:新用户隐藏支票支付脚本的性能优化咨询
问题点分析
- 全量订单查询冗余:原代码用
numberposts => -1拉取当前用户所有已完成订单,而我们仅需确认用户是否存在至少一个符合条件的订单,全量查询会带来不必要的数据库查询和数据传输开销,用户订单越多性能损耗越明显。 - 钩子触发过于频繁:
woocommerce_available_payment_gateways钩子会在多个页面(产品页、购物车页、结账页甚至部分后台页面)触发,每次触发都执行一次数据库查询,重复查询的累积导致页面加载变慢。 - 无结果缓存机制:每次调用
has_bought()都会重新发起数据库查询,相同用户多次访问时会重复执行完全相同的查询操作,没有利用缓存减少重复开销。
优化方案
1. 优化订单查询逻辑
将全量查询改为存在性验证,只确认是否有符合条件的订单存在,大幅减少数据库负载:
function has_bought() { $user_id = get_current_user_id(); if ( $user_id === 0 ) { return false; // 未登录用户直接返回false } // 用wpdb直接执行存在性查询,比get_posts更高效 global $wpdb; $exists = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id WHERE {$wpdb->postmeta}.meta_key = '_customer_user' AND {$wpdb->postmeta}.meta_value = %d AND {$wpdb->posts}.post_type = 'shop_order' AND {$wpdb->posts}.post_status = 'wc-completed' LIMIT 1", $user_id ) ); return $exists > 0; }
如果坚持使用get_posts,也可以调整参数减少返回数据:
function has_bought() { $user_id = get_current_user_id(); if ( $user_id === 0 ) { return false; } $customer_orders = get_posts( array( 'numberposts' => 1, // 仅取1条,确认存在即可 'meta_key' => '_customer_user', 'meta_value' => $user_id, 'post_type' => 'shop_order', 'post_status' => 'wc-completed', 'fields' => 'ids' // 只返回ID,减少数据传输量 ) ); return !empty( $customer_orders ); }
2. 添加查询结果缓存
利用WordPress内置缓存机制,对查询结果进行缓存,避免重复查询:
function has_bought() { $user_id = get_current_user_id(); if ( $user_id === 0 ) { return false; } // 定义缓存键 $cache_key = 'customer_has_completed_order_' . $user_id; $has_bought = wp_cache_get( $cache_key, 'woocommerce' ); if ( false === $has_bought ) { global $wpdb; $exists = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(ID) FROM {$wpdb->posts} LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id WHERE {$wpdb->postmeta}.meta_key = '_customer_user' AND {$wpdb->postmeta}.meta_value = %d AND {$wpdb->posts}.post_type = 'shop_order' AND {$wpdb->posts}.post_status = 'wc-completed' LIMIT 1", $user_id ) ); $has_bought = $exists > 0; // 缓存结果1小时,可根据需求调整有效期 wp_cache_set( $cache_key, $has_bought, 'woocommerce', 3600 ); } return $has_bought; }
也可以将结果存储到用户元数据中,在订单完成时更新,进一步减少查询:
// 订单完成时更新用户元数据 add_action( 'woocommerce_order_status_completed', 'update_customer_bought_meta' ); function update_customer_bought_meta( $order_id ) { $order = wc_get_order( $order_id ); $user_id = $order->get_user_id(); if ( $user_id ) { update_user_meta( $user_id, '_has_completed_order', 'yes' ); } } function has_bought() { $user_id = get_current_user_id(); if ( $user_id === 0 ) { return false; } $has_bought = get_user_meta( $user_id, '_has_completed_order', true ); return $has_bought === 'yes'; }
3. 限制钩子触发场景
只在需要加载支付网关的页面(如结账页、购物车页)执行过滤逻辑,避免无关页面触发:
add_filter('woocommerce_available_payment_gateways', 'customize_payment_gateways'); function customize_payment_gateways($gateways) { // 仅在结账页或购物车页执行逻辑 if ( !is_checkout() && !is_cart() ) { return $gateways; } if (!has_bought()) { if (isset($gateways['cheque'])) { unset($gateways['cheque']); } } return $gateways; }
内容的提问来源于stack exchange,提问作者public9nf
相关产品推荐
相关产品推荐

