Display featured products through custom loop in woocommerce on template page

I would like to display 6 featured products from my woocommerce store on my home-page.php template. After some researched I found that the right way to do this was through a custom loop,( I do not wish to use shortcodes because I would like to add additional classes for styling etc. ) I also found that the key that woocommerce uses for the featured products is ‘_featured’. I put together the code below to display any products that I chose to be featured products in my store, but it doesn’t work… Any help is appreciated.

<?php

    $args = array(
        'post_type'   => 'product',
        'stock'       => 1,
        'showposts'   => 6,
        'orderby'     => 'date',
        'order'       => 'DESC' ,
        'meta_query'  => array(
            array(
                'key'     => '_featured',
                'value'   => 0,
                'compare' => '>',
                'type'    => 'numeric'
            )
        )
    );

    $loop = new WP_Query( $args );
    while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>

        <li>    
            <?php 
                if ( has_post_thumbnail( $loop->post->ID ) ) 
                    echo get_the_post_thumbnail( $loop->post->ID, 'shop_catalog' ); 
                else 
                    echo '<img src="' . woocommerce_placeholder_img_src() . '" alt="Placeholder" width="65px" height="115px" />'; 
            ?>
            <h3><?php the_title(); ?></h3>

            <?php 
                echo $product->get_price_html(); 
                woocommerce_template_loop_add_to_cart( $loop->post, $product );
            ?>    
        </li>

<?php 
    endwhile;
    wp_reset_query(); 
?>

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Change your args to be like this:

$meta_query   = WC()->query->get_meta_query();
$meta_query[] = array(
    'key'   => '_featured',
    'value' => 'yes'
);
$args = array(
    'post_type'   =>  'product',
    'stock'       =>  1,
    'showposts'   =>  6,
    'orderby'     =>  'date',
    'order'       =>  'DESC',
    'meta_query'  =>  $meta_query
);

If you go to wp-content/plugins/woocommerce/includes/class-wc-shortcodes.php (@595) you can find how it’s done for WC shortcodes.

Method 2

This has changed in WooCommerce 3.0. It’s not simply a meta_query, but now includes a tax_query. The arguments are now:

    $meta_query  = WC()->query->get_meta_query();
    $tax_query   = WC()->query->get_tax_query();
    $tax_query[] = array(
        'taxonomy' => 'product_visibility',
        'field'    => 'name',
        'terms'    => 'featured',
        'operator' => 'IN',
    );

    $args = array(
        'post_type'           => 'product',
        'post_status'         => 'publish',
        'ignore_sticky_posts' => 1,
        'posts_per_page'      => $atts['per_page'],
        'orderby'             => $atts['orderby'],
        'order'               => $atts['order'],
        'meta_query'          => $meta_query,
        'tax_query'           => $tax_query,
    );

See woocommerce/includes/class-wc-shortcodes.php

Method 3

Featured Products Loop in WooCommerce 3

<ul class="products">
<?php
$args = array(
    'post_type' => 'product',
    'posts_per_page' => 12,
    'tax_query' => array(
            array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => 'featured',
            ),
        ),
    );
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
    while ( $loop->have_posts() ) : $loop->the_post();
        wc_get_template_part( 'content', 'product' );
    endwhile;
} else {
    echo __( 'No products found' );
}
wp_reset_postdata();
?>

Method 4

According to the WooCommerce Wiki:

Building custom WP_Queries or database queries [to retrieve products] is likely to break your code in future versions of WooCommerce as data moves towards custom tables for better performance.

WooCommerce advocates using wc_get_products() or WC_Product_Query() instead of WP_Query() or get_posts().

I’ve written a post with the code I used to achieve what you want here: https://cfxdesign.com/create-a-custom-woocommerce-product-loop-the-right-way/

Method 5

I know this is quite old, but I’ve just shared an alternative solution here and I think it can help those reaching this topic too.

Instead of using meta_query or tax_query, you can use wc_get_featured_product_ids() too:

$args = array(
    'post_type'           => 'product',
    'posts_per_page'      => 6,
    'orderby'             => 'date',
    'order'               => 'DESC',
    'post__in'            => wc_get_featured_product_ids(),
);

$query = new WP_Query( $args );

I hope it helps!

Method 6

Based on: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query

I would try:

outside loop:

$args = array (
'limit' => 6,
'orderby' => 'title',
'order' => 'ASC',
'category' => $club_cat,
'stock_status' => 'instock',
'featured' => true,

 );

 $products = wc_get_products( $args );

in the loop:

$query = new WC_Product_Query( array(
'limit' => 6,
'orderby' => 'title',
'order' => 'ASC',
'category' => $club_cat,
'stock_status' => 'instock',
'featured' => true,
'return' => 'ids',

 ) );

 $products = $query->get_products();

Method 7

People should start using wc_get_products because woocommerce said this is the standard way of retrieving product. wc_get_products has an argument featured which just needs to be set to true. So the code is simply below.

 <?php 

// Display featured products by category. on this case its "shirts" which is the slug of the category.
$query_args = array(
    'featured' => true,  
    'category' => array( 'shirts' ),
);
$products = wc_get_products( $query_args );

global $post;
$columns = wc_get_loop_prop( 'columns' );
?>
<div class="woocommerce columns-<?php echo esc_attr( $columns ); ?>">
  <?php
    woocommerce_product_loop_start();
    foreach ($products as $product) {
        $post = get_post($product->get_id());
        setup_postdata($post);
        wc_get_template_part('content', 'product');
    }
    wp_reset_postdata();
    woocommerce_product_loop_end();
  ?>
</div>

See full post here: https://jameshwartlopez.com/plugin/get-featured-products-of-a-category/

Method 8

if you take a look in the database in wp_postmeta table you will see meta_key will be _featured and meta_value will be yes or no so instead of value 0 or 1 write yes or no

<?php
    $q = new WP_Query([
      'post_type'   =>  'product',
      'stock'       =>  1,
      'showposts'   =>  3,
      'orderby'     =>  'date',
      'order'       =>  'DESC',
      'meta_query'  =>  [ 
        ['key' => '_featured', 'value' => 'yes' ]
        ]
    ]);
    if ( $q->have_posts() ) :
        while ( $q->have_posts() ) : $q->the_post();
            // display product info
        endwhile; wp_reset_query();
    endif;
?>

Method 9

<ul class="products">
    <?php
        $args = array(
            'post_type' => 'product',
            'posts_per_page' => 12,
            'tax_query' => array(
                    array(
                        'taxonomy' => 'product_visibility',
                        'field'    => 'name',
                        'terms'    => 'featured',
                    ),
                ),
            );
        $loop = new WP_Query( $args );
        if ( $loop->have_posts() ) {
            while ( $loop->have_posts() ) : $loop->the_post();
               echo '<p>'.get_the_title().'</p>';
            endwhile;
        } else {
            echo __( 'No products found' );
        }
        wp_reset_postdata();
    ?>
</ul><!--/.products-->

Method 10

Bump for 2021 – You need to be using wc_get_products()

Also, the code example from Jameshwart (above) didn’t work for me, this is how I set up the postdata & use wc_get_template. Tested & working.

$args = array(
    'status' => 'publish',
    'limit' => 20,
    'paginate' => true, //must be true in order to get ->total
    'return' => 'ids',
);
$products = wc_get_products( $args );

if ($products->total >= 1):

    woocommerce_product_loop_start();

    foreach($products->products as $pid):

        do_action( 'woocommerce_shop_loop' );

        $product = get_post($pid);
        setup_postdata($GLOBALS['post'] =& $product);
        wc_get_template_part('content', 'product');

    endforeach;
    wp_reset_postdata();

    woocommerce_product_loop_end();


endif; //we have products


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x