24

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(); 
?>
1
  • Add the result from var_dump( get_meta_values( '_featured', 'product' ); where the function get_meta_values is supported by the custom function explained in this answer Commented Jul 24, 2015 at 4:34

10 Answers 10

18

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.

2
  • 3
    They key to note is that '_featured' is not stored as a numeric value. It is stored as a string 'yes' or 'no'. Everything else in the OP question should work, worked for me.
    – i_a
    Commented Jul 3, 2016 at 17:02
  • 2
    As of WooCommerce 3.0, this solution no longer works. Please see my updated answer below.
    – dpruth
    Commented Jun 12, 2018 at 19:02
25

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

2
  • 1
    Just what I was looking for!
    – joshkrz
    Commented May 10, 2018 at 22:09
  • Also for Woocommerce 3.0, they recommend using wc_placeholder_img_src instead of woocommerce_placeholder_img_src.
    – Robotnicka
    Commented May 25, 2018 at 0:46
6

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();
?>
6

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/

3
  • sorry, without seeing some written code, it is hard to understand your article. Can you please include some coding ?
    – HOY
    Commented Jun 5, 2019 at 14:59
  • @HOY the embed plugin was broken; it's fixed now and you can see the code!
    – cfx
    Commented Jun 5, 2019 at 20:07
  • thank you, while looking for solutions, I came up with this one below. I am not sure how it differs from yours since I was not able to check yours throughly but it is very short and helped me with a custom product loop. kathyisawesome.com/woocommerce-modifying-product-query
    – HOY
    Commented Jun 5, 2019 at 20:28
2

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!

1

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();
1

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/

0

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;
?>
0
<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-->
1
  • Please edit your answer, and add an explanation: why could that solve the problem?
    – fuxia
    Commented Apr 3, 2019 at 14:40
0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.