skip to Main Content

I’m building a custom category archive template using archive-product.php as a base. What I need to do is show only products from some categories by using the ID of the product category (which is product_cat in Woocommerce). But I want to use wc_get_products rather than a WP_Query post loop, re: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query

"wc_get_products and WC_Product_Query provide a standard way of
retrieving products that is safe to use and will not break due to
database changes in future WooCommerce versions. Building custom
WP_Queries or database queries is likely to break your code in future
versions of WooCommerce as data moves towards custom tables for better
performance."

I’ve copied archive-product.php to the woocommerce folder in my child theme and renamed it custom-category-archive.php, and it has a header of

/*
Template Name: Custom Category Archive Template
*/

so I can select it as a page template in the page editor.

This is the original Woocommerce product loop in the new template custom-category-archive.php:

if ( woocommerce_product_loop() ) {

    /**
     * Hook: woocommerce_before_shop_loop.
     *
     * @hooked woocommerce_output_all_notices - 10
     * @hooked woocommerce_result_count - 20
     * @hooked woocommerce_catalog_ordering - 30
     */
    do_action( 'woocommerce_before_shop_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();

How do I modify the loop to include only the products in the product category (product_cat) by using the category ID? This is how a new WP_Query post loop includes only the products which are in the product categories 12, 345, 7899:

$args = array(
   'post_type' => 'product',
   'post_status' => 'publish',
   'posts_per_page' => '-1',
   'tax_query' => array(
        array(
            'taxonomy'  => 'product_cat',
            'terms'     => array('12,345,7899'),   // including categories by ID
            'operator'  => 'IN',
        )
 

How do I include product categories, i.e. like 12, 345, 7899, in the wc_get_loop_prop('total') post product loop in my custom-category-archive.php template to show only products in those three product categories?

2

Answers


  1. Chosen as BEST ANSWER

    Referencing this outline https://cfxdesign.com/create-a-custom-woocommerce-product-loop-the-right-way/, this is a basic loop for a category archive using wc_get_products:

    defined( 'ABSPATH' ) || exit;
    
    get_header( 'shop' );
    
    do_action( 'woocommerce_before_main_content' );
    
    ?>
    
    <?php
    
    
      if(!function_exists('wc_get_products')) {
        return;
      }
    
    
      $cat_terms = get_field('add_categories_custom_template', $term->term_id);
    
    
      $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'];
     
      $cat_products         = wc_get_products(array(
        'stock_status'      => 'instock',
        'visibility'        => 'visible',
        'status'            => 'publish',
        'limit'             => -1,
        'paginate'          => true,
        'return'            => 'ids',
        'orderby'           => $ordering['orderby'],
        'order'             => $ordering['order'],
    
        'tax_query'             => array(
            array(
                'taxonomy'      => 'product_cat',
                'field'         => 'term_id',
                'terms'         => array('123,45,6789'),
                'operator'      => 'IN',
            )
       )
    
      ));
    
    
     wc_set_loop_prop('total', $cat_products->total);
    
      if($cat_products) {
        do_action('woocommerce_before_shop_loop');
    
        echo '<div id="container">';
    
          foreach($cat_products->products as $cat_product) {
    
            $post_object = get_post($cat_product);
            setup_postdata($GLOBALS['post'] =& $post_object);
    
            echo '<div '; wc_product_class( ' ', $product ); echo '>'; 
    
                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' );
    
            echo '</div>';
    
          }
          wp_reset_postdata();
    
    echo '</div>';
    
        do_action('woocommerce_after_shop_loop');
      } else {
        do_action('woocommerce_no_products_found');
      }
    
    
    do_action( 'woocommerce_after_main_content' );
    

  2. you should try like is –

    $args = array(
        'post_type' => 'product',
        'post_status' => 'publish',
        'posts_per_page' => '-1',
        'tax_query' => array(
             array(
                 'taxonomy'  => 'product_cat',
                 'terms'     => array(12,345,7899),   // including categories by ID
                 'operator'  => 'IN',
             )
        )
    );
    $loop = new WP_Query( $args ); 
        
    while ( $loop->have_posts() ) : $loop->the_post(); 
        print the_title(); 
        the_excerpt(); 
    endwhile;
    
    wp_reset_postdata(); 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search