Get featured products in Woocommerce 3 - php

I want to add Featured products for upsell (or Recent Products OR Best Selling Products) in New order Email template. It works like Upsell with email marketing. How do I add it to woocommerce email template so that there is a section in the end of the email which shows my featured/Recent/best selling products. I tried using this code in my New order Email template but nothing works. I use all latest version of wordpress n woocommerce.
$args = array(
'post_type' => 'product',
'meta_key' => '_featured',
'meta_value' => 'yes',
'posts_per_page' => 1
);
$featured_query = new WP_Query( $args );
if ($featured_query->have_posts()) :
while ($featured_query->have_posts()) :
$featured_query->the_post();
$product = get_product( $featured_query->post->ID );
// Output product information here
endwhile;
endif;
wp_reset_query(); // Remember to reset

Since Woocommerce 3, the products following properties:
"featured",
"stock status",
"catalog visibility"
"rating system"
are now stored like a post term under 'product_visibility' taxonomy, for better performances. So old postmeta data doesn't work anymore.
To make your code working you need instead to make a tax_query this way:
function custom_featured_products(){
$query = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => -1 ,
'tax_query' => array( array(
'taxonomy' => 'product_visibility',
'field' => 'term_id',
'terms' => 'featured',
'operator' => 'IN',
) )
) );
$featured_product_names = array();
if ( $query->have_posts() ): while ( $query->have_posts() ): $query->the_post();
$product = wc_get_product( $query->post->ID );
$featured_product_names[] = $product->get_title();
endwhile; wp_reset_query();endif;
// Testing output
echo '<p>Featured products: ' . implode(', ', $featured_product_names) . '</p>';
}
// Displaying the featured products names in new order email notification
add_action ('woocommerce_email_customer_details', 'new_order_featured_products_display', 30, 4 );
function new_order_featured_products_display( $order, $sent_to_admin, $plain_text, $email ){
// Only for "New Order" email notification
if( 'new_order' != $email->id ) return;
custom_featured_products(); // calling the featured products function output
}
This code goes on function.php file of your active child theme (or theme).
Tested and works.
Updated related to your comments…
Added the code in a function that is called via a hooked function in "New order" email notification.
To get the product image use: $product->get_image( 'shop_thumbnail' );
To get the product link use : $product->get_permalink();

<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-->

Related

WooCommerce: Add multiple cross-sell products to the cart at once with ajax

On my product detail page I'm trying to allow users to add multiple cross-sell products to the cart at once.
I found a few examples how this could be done. But most of them work with URL parameters.
For my case I'm trying to do this with ajax. Like the default add-to-cart button.
On my research I found an example here.
But I'm not sure how to adapt it for my case.
At the moment I have a list of product ID's from a custom loop.
Here's my custom loop code:
add_action('woocommerce_single_product_cols_before', 'show_cross_sell_in_single_product', 1200);
function show_cross_sell_in_single_product(){
$crosssells = get_post_meta( get_the_ID(), '_crosssell_ids',true);
$args = array(
'post_type' => 'product',
'posts_per_page'=> -1,
'post__in' => $crosssells,
'tax_query' => array(
array(
'relation' => 'OR',
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'exclude-from-catalog',
'operator' => 'NOT IN',
),
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => 'exclude-from-catalog',
'operator' => '=',
),
)
),
);
$products_crosssells = new WP_Query( $args );
$products_crosssells_ids = wp_list_pluck( $products_crosssells->posts, 'ID' );
if( $products_crosssells->have_posts() ) : ?>
<div>
<ul>
<?php while ( $products_crosssells->have_posts() ) : $products_crosssells->the_post(); ?>
<?php wc_get_template_part( 'content', 'product-crosssells' ); ?>
<?php endwhile; ?>
</ul>
Add all to the cart
</div>
<?php endif;
wp_reset_postdata();
}
The product ID's are stored in $products_crosssells_ids.
As I understand the example from the link above, I need to add the product ID's to the custom function:
add_action('wp_ajax_multi_add_to_cart', 'multi_ajax_add_to_cart');
add_action('wp_ajax_nopriv_multi_add_to_cart', 'multi_ajax_add_to_cart');
function multi_ajax_add_to_cart() {
if (isset($_POST['items']) ) {
$item_keys = array();
foreach( $_POST['items'] as $item ) {
if( isset($item['id']) ) {
$item_qty = isset($item['qty']) && $item['qty'] > 1 ? $item['qty'] : 1;
$item_keys[] = WC()->cart->add_to_cart($item['id'], $item_qty);
}
}
echo json_encode($item_keys); // Send back cart item keys
}
die();
}
But I'm not sure how I need to add/adapt this code to my product page.
So A user could click on this link and adds everything to the cart:
Add all to the cart

Limit Woocommerce featured products in a WP_Query

I want to get 3 featured products in the header of the site. But my query keeps returning unlimited number of results.
I've been looking online for a solution and came across answers that all answer saying the same thing in terms of the query. What could I be doing wrong?
$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',
'posts_per_page' => 2,
'meta_query' => $meta_query,
'tax_query' => $tax_query,
);
$featured_query = new WP_Query( $args );
if ($featured_query->have_posts()) {
while ($featured_query->have_posts()) :
$featured_query->the_post();
$product = get_product( $featured_query->post->ID );
echo $product->title; echo "test";
// Product info here
endwhile;
}
wp_reset_query();
The following query returned 20 results. The code was placed in header.php. Using woocommerce 3.x.
First your code is a bit outdated, since Woocommerce 3, as get_product() need to be replaced with wc_get_product() and $product->title; by $product->get_title();…
Once done your code works and you will get 3 featured products:
$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',
);
$featured = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => 3, // <== <== <== 3 products
'meta_query' => $meta_query,
'tax_query' => $tax_query,
) );
// Get the products count in the query
echo '<p>Featured products count: ' .$featured->post_count . '</p>';
if ($featured->have_posts()) : while ($featured->have_posts()) :
$featured->the_post();
$product = wc_get_product( $featured->post->ID );
echo $product->get_title() . '<br>';
// Product info here
endwhile; endif;
wp_reset_postdata();
It should work for you as I have tested successfully this code on header.php file…
As before Woocommerce 3, the "featured products" where handled by post meta data (a meta query), you may need to update product terms count going to Woocommerce settings > status > tools. In "Term counts" section click on "Recount terms".
You should be using wp_reset_postdata() instead of wp_reset_query() since WP_query doesn't overwrite the main query.
If that doesn't solve your issue, make sure any other custom loops use the appropriate reset, and/or try renaming the variable $featured_query if you're using it elsewhere - it may be inheriting posts from a previous loop.
You could also try adding the 'nopaging' => true and 'ignore_sticky_posts' => true arguments
I hate to suggest it, but if you can't figure out why it's returning 20 posts instead of 2, you could just break your while loop with a counter:
if ($featured_query->have_posts()) {
$counter = 0;
while ($featured_query->have_posts()) : $featured_query->the_post();
/* Do post stuff here */
$counter++;
if( $counter == 2 ) break;
endwhile;
}

Display a random product thumbnail for a product category in WooCommerce

I am trying to pull a random product thumbnail to display as an image on one of my pages. I can't seem to find a way that works, and have tried the solutions from this and this post.
It would be beneficial to echo it out in a div as well.
Here is what I am currently trying but I'm still unsure how to do this.
functions.php:
function get_random_thumbnails_for_reg(){
if(is_page(381)){
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'allison-1000-gm-duramax-series'
)
)
);
$random_products = get_posts( $args );
foreach ( $random_products as $post ) : setup_postdata( $post );
?>
<div id="randomPic"><?php the_post_thumbnail(); ?></div>
<?php
endforeach;
wp_reset_postdata();
}
}
add_action('wp_footer', 'get_random_thumbnails_for_reg', 50);
Ok after some testing I got it working in a different modular way. I have created a custom shortcode that displays randomly one product thumbnail based on a product category**.
This shortcode has 2 argument:
The product category slug: cat
The image size (can be: 'shop_thumbnail', 'shop_catalog' or 'shop_single')
Then I use this short code in your custom function hooked in wp_footer action hook.
Here is that code:
// Creating a shortcode that displays a random product image/thumbail
if( !function_exists('custom_shortcode_random_thumbnail') ) {
function custom_shortcode_random_thumbnail( $atts ) {
// Shortcode attributes
$atts = shortcode_atts(
array(
'cat' => '', // product category shortcode attribute
'size' => 'shop_thumbnail', // Default image size
),
$atts, 'random_thumbnail'
);
// Get products randomly (from a specific product category)
$random_post = get_posts( array(
'posts_per_page' => 1,
'post_type' => 'product',
'orderby' => 'rand',
'post_status' => 'published',
'tax_query' => array( array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $atts['cat'],
) )
) );
// Get an instance of the WC_Product object
$product = wc_get_product($random_post[0]->ID);
// The Product permalink
$product_permalink = $product->get_permalink();
// The Product image. Size can be: 1. 'shop_thumbnail', 2. 'shop_catalog' or 3. 'shop_single'
$product_image = $product->get_image( $atts['size'] );
// The output
return '<div id="random-pic">' . $product_image . '</div>';
}
add_shortcode( 'random_thumbnail', 'custom_shortcode_random_thumbnail' );
}
// Using the shortcode to display a random product image
function get_random_thumbnails_for_reg(){
// Only for page ID 381
if( ! is_page( 381 ) ) return;
echo do_shortcode( "[random_thumbnail cat='clothing']" );
}
add_action('wp_footer', 'get_random_thumbnails_for_reg', 50);
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works

Display only completed orders on my Woocommerce accounts page

In the account area of my woocommerce shopping site you can click 'orders' and see your order i.e. completed, cancelled, on hold etc etc.
However when you click 'collection' (a page I have made within the account area) I want it to display only 'completed' items.
I have tried to put the following code into the functions.php but with no luck:
(ref - https://businessbloomer.com/woocommerce-display-products-purchased-user/)
add_shortcode( 'my_products', 'bbloomer_user_products_bought' );
function bbloomer_user_products_bought() {
global $product, $woocommerce, $woocommerce_loop;
$columns = 3;
$current_user = wp_get_current_user();
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array('catalog', 'visible'),
'compare' => 'IN'
)
)
);
$loop = new WP_Query($args);
ob_start();
woocommerce_product_loop_start();
Loop part
while ( $loop->have_posts() ) : $loop->the_post();
$theid = get_the_ID();
if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $theid ) ) {
wc_get_template_part( 'content', 'product' );
}
endwhile;
woocommerce_product_loop_end();
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
and then adding the shortcode:
[my_products]
when you click the collection link it does not display anything - well generates a div with nothing in it!
Is there a better way of doing this or a alternative?
Replace your $args with bellow code
$args = array(
'post_type' => 'shop_order',
'post_status' => 'wc-completed'
);
Then let me know the result. Thanks

Custom sort of featured products in woocommerce

Can any body please help me to sort the featured products only using different sorting attributes like price,date in woo-commerce.
I have tried the code
function sort_by()
{
$args = array(
'post_type' => 'product',
'meta_key' => '_featured',
'meta_value' => 'yes',
'posts_per_page' => '-1',
'orderby' => $_POST['sorter'] ,
'order'=>'ASC'
);
$featured_query = new WP_Query( $args );
print_r($featured_query);
if ($featured_query->have_posts()) :
while ($featured_query->have_posts()) :
$featured_query->the_post();
$product = get_product( $featured_query->post->ID );
echo the_title();
endwhile;
endif;
wp_reset_query(); // Remember to reset
die();
}
add_action('wp_ajax_sort_by','sort_by');
add_action('wp_ajax_no-prev_sort_by','sort_by');
The above code works when ajax hit but it's cannot sort the feature products according to date, price, popularity and rating.

Categories