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

Woocommerce 8.x.x相关产品自定义问题:缓存与主类别筛选失效

WooCommerce相关产品自定义问题解决方案

问题1:强制存储自定义查询结果以降低服务器负载

要避免每次页面请求都执行自定义查询,可利用WordPress的Transient缓存机制持久化存储查询结果,具体实现如下:

  • 缓存查询结果:根据当前产品ID、主类别及语言生成唯一缓存键,先检查是否存在对应缓存。若缓存有效,直接返回缓存的产品ID列表;若不存在,执行自定义查询后将结果存入Transient,设置合理过期时间(如24小时)。
  • 缓存失效机制:在产品更新、类别调整时,通过save_post_product、edited_term等钩子清除对应缓存,保证数据时效性。

示例代码片段(结合你的业务逻辑):

function custom_related_products_query( $query, $product_id ) {
    global $wpdb;

    // 生成唯一缓存键(包含语言标识适配多语言场景)
    $cache_key = 'related_products_main_cat_' . $product_id . '_' . get_locale();
    $cached_ids = get_transient( $cache_key );

    if ( $cached_ids ) {
        // 直接使用缓存构建查询结构
        $query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p WHERE p.ID IN (" . implode(',', $cached_ids) . ")";
        $query['join'] = '';
        $query['where'] = " AND p.post_status = 'publish' AND p.post_type = 'product'";
        return $query;
    }

    // 获取产品主类别(使用WooCommerce官方方法)
    $main_category_id = wc_get_product_term_id( $product_id, 'product_cat' );
    $main_category = get_term( $main_category_id, 'product_cat' );

    if ( ! $main_category || is_wp_error( $main_category ) ) {
        return $query;
    }

    // 执行自定义查询获取相关产品ID
    $related_ids = $wpdb->get_col(
        "SELECT DISTINCT p.ID FROM {$wpdb->posts} p
        INNER JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id
        INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
        WHERE p.post_status = 'publish' 
        AND p.post_type = 'product' 
        AND p.ID != {$product_id}
        AND tt.taxonomy = 'product_cat' 
        AND tt.term_id = {$main_category->term_id}"
    );

    // 存储缓存,24小时后过期
    set_transient( $cache_key, $related_ids, 24 * HOUR_IN_SECONDS );

    // 构建最终查询结构返回
    $query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p WHERE p.ID IN (" . implode(',', $related_ids) . ")";
    $query['join'] = '';
    $query['where'] = " AND p.post_status = 'publish' AND p.post_type = 'product'";
    return $query;
}
add_filter( 'woocommerce_product_related_posts_query', 'custom_related_products_query', 99, 2 );

问题2:强制相关产品取自同一主类别无效的排查思路

结合你提供的$query数组和代码,从以下维度排查:

1. 主类别获取逻辑错误

你当前通过$category->parent == 0判断顶级类别作为主类别,但WooCommerce中产品的主类别是用户在产品编辑页手动选择的(可能是子类别),而非默认顶级类别。应改用官方函数获取真正的主类别:

// 替换原有的主类别遍历逻辑
$main_category_id = wc_get_product_term_id( $product_id, 'product_cat' );
$main_category = get_term( $main_category_id, 'product_cat' );

2. 重复JOIN导致关联冲突

你的代码中追加了INNER JOIN {$wpdb->term_relationships}和INNER JOIN {$wpdb->term_taxonomy},但原$query的join字段已包含这些表的关联(从你提供的$query数组可见),重复关联会导致SQL逻辑错误,甚至返回空结果。建议直接修改原查询的WHERE条件,而非追加JOIN。

3. 钩子优先级被覆盖

你设置的钩子优先级为10,可能被其他插件或主题的同钩子逻辑覆盖。将优先级调高(如99),确保你的修改最后执行:

add_filter( 'woocommerce_product_related_posts_query', 'custom_related_products_query', 99, 2 );

4. 调试验证步骤

  • 在函数中添加var_dump($main_category),确认主类别是否正确获取;
  • 将最终生成的SQL语句(拼接$query['fields'] + $query['join'] + $query['where'] + $query['limits'])复制到数据库管理工具执行,查看返回结果是否符合预期;
  • 检查多语言插件(如WPML,你的$query中包含icl_translations表)干扰,确认语言过滤条件icl.language_code = 'fr'是否影响主类别下的产品筛选。

修改后的核心代码

if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

    function custom_related_products_query( $query, $product_id ) {
        global $wpdb;

        $categories = get_the_terms( $product_id, 'product_cat' );
        if ( empty( $categories ) || is_wp_error( $categories ) ) {
            return $query;
        }

        // 获取WooCommerce官方认定的主类别
        $main_category_id = wc_get_product_term_id( $product_id, 'product_cat' );
        $main_category = get_term( $main_category_id, 'product_cat' );

        if ( ! $main_category || is_wp_error( $main_category ) ) {
            return $query;
        }

        // 清理原查询中多余的类别条件,添加主类别过滤
        $query['where'] = preg_replace( '/AND WCCP_term_taxonomy\.term_id = \d+/', '', $query['where'] );
        $query['where'] .= " AND {$wpdb->term_taxonomy}.taxonomy = 'product_cat' AND {$wpdb->term_taxonomy}.term_id = {$main_category->term_id}";

        return $query;
    }
    // 提高优先级确保最后执行
    add_filter( 'woocommerce_product_related_posts_query', 'custom_related_products_query', 99, 2 );

    function custom_related_products_orderby( $orderby ) {
        return "p.ID DESC";
    }
    add_filter( 'woocommerce_product_related_posts_orderby', 'custom_related_products_orderby', 10, 1 );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:59:52