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
相关产品推荐
相关产品推荐

