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

WooCommerce多站点:自定义产品字段前置过滤产品循环需求

解决WooCommerce多站点产品可见性前置过滤问题

我创建了7个自定义产品复选框字段,用于WooCommerce(WordPress网络)多站点的子站点中控制产品可见性。当前代码可实现功能,但是在产品循环输出后才进行过滤,导致多数店铺页面几乎为空(共89个页面,大多无产品或仅少量产品)。需要在产品循环输出前完成过滤,使各子站点拥有数量合适的完整产品页面(例如12个),现有代码如下:

if ( woocommerce_product_loop() ) {

    woocommerce_product_loop_start();

    if ( wc_get_loop_prop( 'total' ) ) {

        global $product;

        $blog_id = get_current_blog_id();

        while ( have_posts() ) {
            the_post();

            if ($blog_id == '1') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_3rdmillennium', true );
            } elseif ($blog_id == '2') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_fight2win', true );
            } elseif ($blog_id == '3') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_muaythai', true );
            } elseif ($blog_id == '4') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_taekwondo', true );
            } elseif ($blog_id == '5') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_xprtfightgear', true );
            } elseif ($blog_id == '6') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_hayabusashop', true );
            } elseif ($blog_id == '7') {
                $visibility = get_post_meta( $product->get_id(), '_visibility_kmushop', true );
            }

            if ($visibility == 'yes') {
                /**
                 * Hook: woocommerce_shop_loop.
                 */
                do_action( 'woocommerce_shop_loop' );

                wc_get_template_part( 'content', 'product' );
            }

        }

    }
}

解决方案:前置查询过滤

核心是利用pre_get_posts钩子在WP_Query执行前添加筛选条件,直接从数据库中获取符合当前站点可见性要求的产品,确保分页正常、每页产品数量符合设置。

1. 添加前置过滤钩子函数

将以下代码添加到主题的functions.php文件或自定义插件中:

// 在产品查询前添加站点可见性过滤
add_action( 'pre_get_posts', 'filter_products_by_site_visibility' );
function filter_products_by_site_visibility( $query ) {
    // 仅对前台主产品查询生效(店铺页、产品分类/标签页)
    if ( ! is_admin() && $query->is_main_query() && ( is_shop() || is_product_category() || is_product_tag() ) ) {
        $blog_id = get_current_blog_id();
        
        // 建立博客ID与对应可见性元字段的映射表,替代冗长的if-else
        $visibility_fields = [
            1 => '_visibility_3rdmillennium',
            2 => '_visibility_fight2win',
            3 => '_visibility_muaythai',
            4 => '_visibility_taekwondo',
            5 => '_visibility_xprtfightgear',
            6 => '_visibility_hayabusashop',
            7 => '_visibility_kmushop',
        ];
        
        // 如果当前站点在映射列表中,添加元查询条件
        if ( isset( $visibility_fields[ $blog_id ] ) ) {
            $meta_query = $query->get( 'meta_query', [] );
            $meta_query[] = [
                'key'     => $visibility_fields[ $blog_id ],
                'value'   => 'yes',
                'compare' => '=',
            ];
            $query->set( 'meta_query', $meta_query );
        }
    }
}

2. 简化产品循环代码

移除原循环内的过滤逻辑,恢复标准的WooCommerce产品循环:

if ( woocommerce_product_loop() ) {

    woocommerce_product_loop_start();

    if ( wc_get_loop_prop( 'total' ) ) {
        while ( have_posts() ) {
            the_post();

            /**
             * Hook: woocommerce_shop_loop.
             */
            do_action( 'woocommerce_shop_loop' );

            wc_get_template_part( 'content', 'product' );
        }
    }

    woocommerce_product_loop_end();

}

方案优势

  • 高效过滤:在数据库查询阶段就筛选产品,避免先查所有产品再循环过滤的资源浪费
  • 分页正常:查询结果直接符合每页产品数量设置,不会出现页面为空的情况
  • 代码易维护:用数组映射替代大量if-else,后续新增站点只需在映射表中添加字段即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:10:48