
在构建复杂的 woocommerce 商店时,开发者经常需要创建自定义页面来展示特定分类下的产品。例如,您可能希望在一个特殊的“特价商品”页面中,只显示特定几个产品分类(如“电子产品”和“服装”)中的商品。传统上,许多开发者会倾向于使用 wp_query 来实现这一目标。然而,对于 woocommerce 产品,官方推荐使用 wc_get_products 函数,因为它提供了更好的兼容性和性能优化。
wc_get_products 和 WC_Product_Query 提供了一种标准化的方式来检索产品,这种方式安全且不会因未来 WooCommerce 数据库结构的变化而中断。随着 WooCommerce 数据逐渐向自定义表迁移以提升性能,直接构建 WP_Query 或数据库查询很可能会在未来的 WooCommerce 版本中导致代码失效。因此,采用 wc_get_products 是一个更具前瞻性和稳健性的选择。
首先,您需要在子主题中创建一个自定义的 WooCommerce 模板文件。
将 woocommerce/archive-product.php 文件复制到您的子主题的 woocommerce 文件夹中。
将其重命名为 custom-category-archive.php(或其他您喜欢的名称)。
在该文件的顶部添加以下模板头,以便在 WordPress 页面编辑器中选择它作为页面模板:
<?php /* Template Name: Custom Category Archive Template */ ?>
在 WordPress 后台创建一个新页面,并在页面属性中选择“Custom Category Archive Template”作为模板。
现在,我们将在 custom-category-archive.php 文件中替换默认的 WooCommerce 产品循环,使用 wc_get_products 来筛选产品。
wc_get_products 函数接受一个包含查询参数的数组,类似于 WP_Query 的 $args。要按产品分类 ID 筛选,我们需要使用 tax_query 参数。
以下是一个基本的 wc_get_products 查询示例,用于获取指定分类 ID(例如 123, 45, 6789)下的所有产品:
<?php
defined( 'ABSPath' ) || exit;
// 确保 wc_get_products 函数存在
if ( ! function_exists( 'wc_get_products' ) ) {
return;
}
// 获取当前的目录排序参数
$ordering = WC()->query->get_catalog_ordering_args();
$ordering['orderby'] = array_shift( explode( ' ', $ordering['orderby'] ) );
$ordering['orderby'] = stristr( $ordering['orderby'], 'price' ) ? 'meta_value_num' : $ordering['orderby'];
// 构建 wc_get_products 查询参数
$args = array(
'stock_status' => 'instock', // 只显示有库存的产品
'visibility' => 'visible', // 只显示可见产品
'status' => 'publish', // 只显示已发布产品
'limit' => -1, // 显示所有产品,不分页
'paginate' => true, // 启用分页(即使 limit 为 -1,也建议设置为 true,以便获取总数)
'return' => 'ids', // 只返回产品 ID
'orderby' => $ordering['orderby'], // 使用商店默认排序方式
'order' => $ordering['order'], // 使用商店默认排序顺序
'tax_query' => array(
array(
'taxonomy' => 'product_cat', // 分类法为产品分类
'field' => 'term_id', // 根据分类 ID 筛选
'terms' => array( 123, 45, 6789 ), // 指定要包含的产品分类 ID 数组
'operator' => 'IN', // 包含在指定 ID 列表中的分类
)
)
);
// 执行查询
$cat_products = wc_get_products( $args );
// 设置 WooCommerce 循环属性,以便其他函数(如分页)可以访问总数
wc_set_loop_prop( 'total', $cat_products->total );
?>参数解释:
获取到产品 ID 列表后,我们需要遍历这些 ID,并使用 WooCommerce 的标准钩子来显示每个产品。
将以下代码整合到您的 custom-category-archive.php 文件中,替换掉原有的 while ( have_posts() ) 循环部分:
<?php
// ... (之前的 wc_get_products 查询代码) ...
get_header( 'shop' ); // 获取商店头部
do_action( 'woocommerce_before_main_content' ); // WooCommerce 主内容前钩子
?>
<?php if ( $cat_products && $cat_products->products ) : ?>
<?php do_action( 'woocommerce_before_shop_loop' ); // 商店循环前钩子 ?>
<div id="container" class="products columns-<?php echo esc_attr( wc_get_loop_prop( 'columns' ) ); ?>">
<?php foreach ( $cat_products->products as $product_id ) : ?>
<?php
// 获取产品对象并设置全局 $post 变量
$post_object = get_post( $product_id );
setup_postdata( $GLOBALS['post'] =& $post_object );
$product = wc_get_product( $product_id ); // 获取 WC_Product 对象
?>
<div <?php wc_product_class( '', $product ); ?>>
<?php
/**
* 钩子: woocommerce_before_shop_loop_item.
*
* @hooked woocommerce_template_loop_product_link_open - 10
*/
do_action( 'woocommerce_before_shop_loop_item' );
/**
* 钩子: woocommerce_before_shop_loop_item_title.
*
* @hooked woocommerce_show_product_loop_sale_flash - 10
* @hooked woocommerce_template_loop_product_thumbnail - 10
*/
do_action( 'woocommerce_before_shop_loop_item_title' );
/**
* 钩子: woocommerce_shop_loop_item_title.
*
* @hooked woocommerce_template_loop_product_title - 10
*/
do_action( 'woocommerce_shop_loop_item_title' );
/**
* 钩子: woocommerce_after_shop_loop_item_title.
*
* @hooked woocommerce_template_loop_rating - 5
* @hooked woocommerce_template_loop_price - 10
*/
do_action( 'woocommerce_after_shop_loop_item_title' );
/**
* 钩子: woocommerce_after_shop_loop_item.
*
* @hooked woocommerce_template_loop_add_to_cart - 10
* @hooked woocommerce_template_loop_product_link_close - 10
*/
do_action( 'woocommerce_after_shop_loop_item' );
?>
</div>
<?php endforeach; ?>
<?php wp_reset_postdata(); // 重置全局 $post 变量 ?>
</div><!-- #container -->
<?php do_action( 'woocommerce_after_shop_loop' ); // 商店循环后钩子 ?>
<?php else : ?>
<?php do_action( 'woocommerce_no_products_found' ); // 未找到产品时钩子 ?>
<?php endif; ?>
<?php
do_action( 'woocommerce_after_main_content' ); // WooCommerce 主内容后钩子
get_footer( 'shop' ); // 获取商店底部
?>代码解释:
将上述所有代码片段组合起来,您的 custom-category-archive.php 文件将如下所示:
<?php
/*
Template Name: Custom Category Archive Template
*/
defined( 'ABSPath' ) || exit;
get_header( 'shop' );
do_action( 'woocommerce_before_main_content' );
// 确保 wc_get_products 函数存在
if ( ! function_exists( 'wc_get_products' ) ) {
do_action( 'woocommerce_no_products_found' ); // 如果函数不存在,显示未找到产品
do_action( 'woocommerce_after_main_content' );
get_footer( 'shop' );
return;
}
// 获取当前的目录排序参数
$ordering = WC()->query->get_catalog_ordering_args();
$ordering['orderby'] = array_shift( explode( ' ', $ordering['orderby'] ) );
$ordering['orderby'] = stristr( $ordering['orderby'], 'price' ) ? 'meta_value_num' : $ordering['orderby'];
// 构建 wc_get_products 查询参数
$args = array(
'stock_status' => 'instock',
'visibility' => 'visible',
'status' => 'publish',
'limit' => -1, // -1 表示不限制数量,显示所有匹配产品
'paginate' => true,
'return' => 'ids', // 只返回产品 ID
'orderby' => $ordering['orderby'],
'order' => $ordering['order'],
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id',
'terms' => array( 123, 45, 6789 ), // 替换为您的产品分类 ID
'operator' => 'IN',
)
)
);
// 执行查询
$cat_products = wc_get_products( $args );
// 设置 WooCommerce 循环属性,以便其他函数(如分页)可以访问总数
wc_set_loop_prop( 'total', $cat_products->total );
if ( $cat_products && $cat_products->products ) : ?>
<?php do_action( 'woocommerce_before_shop_loop' ); ?>
<div id="container" class="products columns-<?php echo esc_attr( wc_get_loop_prop( 'columns' ) ); ?>">
<?php foreach ( $cat_products->products as $product_id ) : ?>
<?php
$post_object = get_post( $product_id );
setup_postdata( $GLOBALS['post'] =& $post_object );
$product = wc_get_product( $product_id ); // 获取 WC_Product 对象
?>
<div <?php wc_product_class( '', $product ); ?>>
<?php
do_action( 'woocommerce_before_shop_loop_item' );
do_action( 'woocommerce_before_shop_loop_item_title' );
do_action( 'woocommerce_shop_loop_item_title' );
do_action( 'woocommerce_after_shop_loop_item_title' );
do_action( 'woocommerce_after_shop_loop_item' );
?>
</div>
<?php endforeach; ?>
<?php wp_reset_postdata(); ?>
</div><!-- #container -->
<?php do_action( 'woocommerce_after_shop_loop' ); ?>
<?php else : ?>
<?php do_action( 'woocommerce_no_products_found' ); ?>
<?php endif;
do_action( 'woocommerce_after_main_content' );
get_footer( 'shop' );通过采用 wc_get_products 函数并结合 tax_query 参数,您可以安全、高效地在 WooCommerce 自定义模板中按产品分类 ID 筛选和显示产品。这种方法不仅保证了代码的未来兼容性,还通过集成 WooCommerce 的标准钩子,确保了与现有生态系统的良好协作。遵循本教程的步骤,您将能够构建出功能强大且维护友好的自定义产品列表页面。
以上就是在 WooCommerce 自定义循环中按产品分类 ID 筛选产品的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号