'Get WooCommerce products from specific category
I am trying to insert a WooCommerce element to display "products" (courses) from a specific category into a page.
I had also to hide these products for this specific category and it worked as expected. I just added a a filter inside functions.php and was it:
/*
* Exclude "packages" category from "Archive Products" on page 811
* Ref. URL: https://docs.woocommerce.com/document/exclude-a-category-from-the-shop-page/
*/
function exclude_category_archive_products( $q ) {
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'packages' ),
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
if( $current_post_id != "811" ) {
add_filter( 'woocommerce_product_query', 'exclude_category_archive_products' );
}
/* END Exclude "packages" category from "Archive Products" on page 811 */
I have searched for ways to to achieve the opposite and I did not find anything "from this year or close". I've tried to use the "IN" or "=" operator but it didn't work (it displays everything):
/*
* Display "packages" category only
*/
function show_only_category_in_page( $q ) {
var_dump("It reaches the function");
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'packages' ),
'operator' => '='
);
$q->set( 'tax_query', $tax_query );
}
if( $current_post_id == "811" ) {
var_dump("It reaches the page");
add_filter( 'woocommerce_product_query', 'show_only_category_in_page' );
}
/* END Display "packages" category only */
The previous code writes the string(23) "It gets reachs the page"
only. What am I doing wrong?
Solution 1:[1]
You should try this for that you can get products from a specific category
Solution 1:
$prod_categories = array(1, 2,3);
$product_args = array(
'numberposts' => $limit,
'post_status' => array('publish', 'pending', 'private', 'draft'),
'post_type' => array('product', 'product_variation'),
'orderby' => 'ID',
'suppress_filters' => false,
'order' => 'ASC',
'offset' => 0
);
if (!empty($prod_categories)) {
$product_args['tax_query'] = array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $prod_categories,
'operator' => 'IN',
));
}
$products = get_posts($product_args);
Where 1,2,3 your category id.
Solution 2
Create a custom page and show specific categories of products:
<?php
/**
* Template Name: Courses template
*
*/
defined( 'ABSPATH' ) || exit;
get_header();
?>
<div id="content" class="content" role="main">
<ul class="products">
<?php
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'product_cat' => 'clothing', // Category slug "clothing"
'orderby' => 'rand'
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>
<h2>Courses</h2>
<li class="product">
<a href="<?php echo get_permalink( $loop->post->ID ) ?>" title="<?php echo esc_attr($loop->post->post_title ? $loop->post->post_title : $loop->post->ID); ?>">
<?php woocommerce_show_product_sale_flash( $post, $product ); ?>
<?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="300px" height="300px" />'; ?>
<h3><?php the_title(); ?></h3>
<span class="price"><?php echo $product->get_price_html(); ?></span>
</a>
<?php woocommerce_template_loop_add_to_cart( $loop->post, $product ); ?>
</li>
<?php endwhile; ?>
<?php wp_reset_query(); ?>
</ul>
</div><!-- #content -->
<?php get_footer(); ?>
Steps:
- Go to your active theme create a new page like course-tpl.php
- Copy and paste the above code on your custom page course-tpl.php and change/replace category slug "clothing" to "your category slug" and save.
- Open dashboard - go to pages and "Add New" page enter a page title and assign "Courses template" and save
- Open new page
- Update/manage page CSS and HTML accordingly.
Solution 2:[2]
Get products of specific product category (by category slug or id):
I would like to update Rajeev Singh's solution, especially the solution for displaying products of specific product categories.
Problem:
According to Woocommerce documentation WP_Query() or get_posts() should not be used:
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. This is the best-practices way for plugin and theme developers to retrieve multiple products. wc_get_products and WC_Product_Query are similar to WordPress get_posts and WP_Query. Just like those, you pass in an array of arguments defining the criteria for the search.
Solution 1 - get products by category slug
Note: category argument requires an array of slugs, not IDs.
If you would like use the id of the product category on the specific category archive page check solution 2. How to get the ID of the current category from the category archive page template is not part of this solution.
<?php
$product_term_slugs = array('shirts');
$product_args = array(
'post_status' => 'publish',
'limit' => -1,
'category' => $product_term_slugs,
//more options according to wc_get_products() docs
);
$products = wc_get_products($product_args);
?>
Solution 2 - get products by category id:
$product_term_ids = array(12);
$product_term_args = array(
'taxonomy' => 'product_cat',
'include' => $product_term_ids,
'orderby' => 'include'
);
$product_terms = get_terms($product_term_args);
$product_term_slugs = [];
foreach ($product_terms as $product_term) {
$product_term_slugs[] = $product_term->slug;
}
$product_args = array(
'post_status' => 'publish',
'limit' => -1,
'category' => $product_term_slugs,
//more options according to wc_get_products() docs
);
$products = wc_get_products($product_args);
Solution - display products
<?php foreach ($products as $product) {
$product_id = $product->get_id();
$product_type = $product->get_type();
$product_title = $product->get_title();
$product_permalink = $product->get_permalink();
$product_regular_price = $product->get_regular_price();
$product_sale_price = $product->get_sale_price();
$product_short_desc = $product->get_short_description();
$product_categories = $product->get_categories();
?>
<!-- display product html -->
<?php } ?>
(Tested and works with Wordpress 5.9.3 & WooCommerce 6.4.1.)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Rajeev Singh |
Solution 2 | J Grandjean |