WooCommerce: Get average rating from multiple products [duplicate] - php

This question already has an answer here:
Display total customers reviews and ratings average in WooCommerce
(1 answer)
Closed last year.
I've a custom loop to get a list of products based on a list of product IDs.
Now I try to get the total ratings and average rating of all the products within that loop.
The total count of ratings isn't the problem.
My problem is that I don't get the star rating from the comments.
(I'm using the plugin "WooCommerce Product Reviews Pro")
Here's my current loop so far:
<?php $args = array (
'post_type' => 'product',
'number' => '-1',
'post__in' => $product_ids,
'meta_key' => 'rating',
'orderby' => 'meta_value_num',
'order' => 'DESC'
);
$comments = get_comments( $args );
echo count($comments);
?>
<?php if ( !empty($comments) ) : ?>
<pre><?php print_r($comments); ?></pre>
<?php foreach ( $comments as $comment ) {
echo $comment_ID = $comment->comment_ID;
} ?>
<?php endif; ?>
With echo count($comments) I get the total count of ratings.
But if I do print_r($comments), I don't see the star rating for the review.
I guess that I need to use the comment ID for that.
With the foreach I get all comment Ids as a string.
But I'm not sure where to look and how I add all ratings to generate a new average rating for the selected posts from the loop.
EDIT: I found another way to get to the average ratings.
This time I loop through the posts instead the comments.
So I can get the average rating for every product.
The problem is that in that loop are also ratings with a 0 if there are no comments/reviews.
Here's the loop for the product so far:
$average_ratings = array();
foreach ( $posts as $post ) {
global $product;
echo $average_ratings[] = $product->get_average_rating();
}
var_dump($average_ratings);

I found an answer. This is my code:
<?php
$args = array (
'post_type' => 'product',
'post__in' => $product_ids,
'meta_key' => 'rating',
'orderby' => 'meta_value_num',
'order' => 'DESC'
);
$comments = get_comments( $args );
$total_ratings = count($comments);
?>
<?php if ( !empty($comments) ) : ?>
<?php
$average_ratings = array();
foreach ( $comments as $comment ) {
$comment_post_ID = $comment->comment_post_ID;
$product = wc_get_product( $comment_post_ID );
$average_ratings[] = $product->get_average_rating();
}
$average_ratings = array_filter($average_ratings);
$average = array_sum($average_ratings)/count($average_ratings);
echo $average;
?>
<?php endif; ?>

Related

wc_update_order_item not saving correctly

I'm trying to update the Item Name in the wp_woocommerce_order_items table and found the function wc_update_order_item to do the trick.
I want it to change to a randomly picked product. They main thing here is I already know the order_item_id that I want to change.
Here's my code:
$order_item_id = array(1,2,3);
$num = 3;
$ctr = 0;
$products = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $num,
'orderby' => 'rand',
));
if ( $products->have_posts() ): while ( $products->have_posts() ): $products->the_post();
wc_update_order_item($order_item_id[$ctr], array('order_item_name' => $products->post->post_title));
$ctr++;
endwhile; wp_reset_postdata(); endif;
The wc_update_order_item() is where it is supposed to update the order item name. It does update the order_item_name but not with the current $products->post->post_title value. It updates with with a random product title.
How do I know the title being saved is different from the current post_title inside the loop? If I echo $products->post->post_title inside the loop, it displays the current product name, as it should, but the updated order_item_name has a different value.
Try the following that will get the related product IDs corresponding to the Order items, to exclude them from the WP_Query, avoiding having the same product names:
$order_item_ids = array(1,2,3);
$num = 3;
$ctr = 0;
$exluded_ids = array();
// Loop through the Order items Ids
foreach ( $order_item_ids as $item_id ) {
// Get the order ID from the order Item ID
$order_id = wc_get_order_id_by_order_item_id( $item_id );
// Get the WC_Order object instance
$order = wc_get_order( $order_id );
// Get the WC_Order_Item_Product object instance
$item = $order->get_item( $item_id );
// Products IDs to be excluded from the WP_Query (array)
$exluded_ids[] = $item->get_product_id();
}
$products = new WP_Query( array(
'post_type' => 'product',
'post_status' => 'publish',
'posts_per_page' => $num,
'orderby' => 'rand',
'post__not_in' => $exluded_ids,
));
if ( $products->have_posts() ):
while ( $products->have_posts() ): $products->the_post();
wc_update_order_item($order_item_id[$ctr], array('order_item_name' => $products->post->post_title));
$ctr++;
endwhile;
wp_reset_postdata();
endif;
It should work.
Now as we don't know how you get the $order_item_id array, it's not possible to know what really happen. It should be better to explain what you are trying to do from the start.

How to get_terms $count for custom-taxonomy

Have a custom-taxonomy called campaign_action with three categories called draft, live and paused.
I would like to display just the count for each but not in a list.
For example, I would like to echo the count for each individually as -
<li>Draft (<?php //code to display a number count for drafts ?>)</li>
<li>Live (<?php //code to display a number count for live ?>)</li>
<li>Paused (<?php //code to display a number count for paused ?>)</li>
I have successfully done this by displaying
foreach ( $terms as $term ) {
echo '(' . $term->count . ')';
}
However, this does not work for me and I want to get the $count for each individually.
Thank you for your help.
EDIT
To show further what I have in place currently
<?php
$terms = get_terms('campaign_action');
if ( !empty( $terms ) && !is_wp_error( $terms ) ){
echo '(0)';
foreach ( $terms as $term ) {
echo '(' . $term->count . ')';
}
}
?>
This will show all counts for each individual category but I only want to show the count for the category of draft within the custom_taxonomy of campaign_action
Here is an image of what the above achieves when added to the end of the Drafts. I want it to only show the count for the category of drafts within the custom-taxonomy of campaign_action. If it has zero posts with that category then it should show zero.
Try below code and read my comments of code.
echo wp_list_categories( array(
'orderby' => 'name',
'show_count' => true,
'taxonomy' => 'campaign_action' //i guess campaign_action is your taxonomy
) );
There is second way as well for custom html layout please check below code for custom html layout
$terms = get_terms(array(
'taxonomy' => 'campaign_action',//i guess campaign_action is your taxonomy
'hide_empty' => false
));
echo $terms->name;
echo $terms->count;
After Your question is edited :
$terms = get_terms(array(
'taxonomy' => 'campaign_action',//i guess campaign_action is your taxonomy
'hide_empty' => false
));
foreach ($terms as $terms)
{
if($terms->name == 'Draft')
{
echo $terms->name;
echo $terms->count;
}
}
You need to some arguments :
<?php
$args = array(
'post_type' => 'campaign_action',
'post_status' => 'publish' //(Or Draft...etc)
);
$show_recipes= get_posts( $args );
echo $show_recipes->post_count;
?>
Here is the full list of statuses in WP : https://codex.wordpress.org/Post_Status

Counting posts in category and auto removing from category

my posts are listed in 2 categories. (featured, news).
iam trying to count posts in 'featured' category, and if its more than 5 i want it to remove 6,7,8, ...
only keep latest 5..
so far iam able to count them using this code
$category = get_category(830);
$count = $category->category_count;
if( $count > 5 ) {
// stuff
}
but inside the if statement how to get items 6,7,8... ?
i just want to remove category "featured" with category_id 830, and keep other category (news) if its listed in it.
i made this function , but i get error 500 when i use it.
can you help me?
$my_query = new WP_Query( 'category_name=featured' );
function countfeatures($my_query) {
$featurecount = 0;
while ( $my_query->have_posts() ) : $my_query->the_post();
$featurecount++;
if ($featurecount > 5){
$pos = array_search( 'featured', $post_cats );
unset( $post_cats[$pos] );
wp_set_post_terms ($post_id, $post_cats, 'category');
//wp_set_post_terms ($slide->ID, $post_cats, 'category');
//do stuff
}
endwhile;
}
add_filter('pre_get_posts', 'countfeatures');
Use Limit in query for 5 and Order by Primary key descending,so You will get top five latest record
Only orderby and order parameter needs to be added this will get you
newest 5 posts of featured category.
$args = array(
'post_type' => 'post',
'post_status'=> 'publish',
'posts_per_page'=>5,
'order'=>'DESC',
'orderby'=>'ID',
'tax_query' => array(
array(
'taxonomy' => 'featured',
'field' => 'term_id',
'terms' => array(830),
'operator' => 'IN',
),
),
);
$query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();

Woocommerce get product ID's from Category

So on my template for taxonomy-product_tag.php, I want to get all product id's from the Category.
Here is how I currently do it
<?php
$post_ids = array();
$args = array( 'post_type' => 'product', 'posts_per_page' => 1, 'product_cat' => 'dog-collars', 'orderby' => 'rand' );
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
$post_ids[] = get_the_ID();
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_query();
print_r($post_ids);
?>
I can loop through the product_cat, pull id's into an array and then further down the page I use foreach and the WC product factory to manipulate data how I want it shown for users.
My problem is I need the loop to be Dynamic based on categories, and I can't understand how to do this.
I did think I can just grab the category name from the url
<?php $actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; ?>
Grab it and the parse to just get the last , i.e category name, and then print into loop
But this seems like it would be a really poor way of doing it.
What I want is in the args
$args = array( 'post_type' => 'product', 'posts_per_page' => 1, 'product_cat' => 'DYNAMICHERE', 'orderby' => 'rand' );
I want to be able to populate product_cat dynamically based on the category I am on
Any help or advise / pointing me in the right direction would be appreciated
Use get_query_var( 'product_cat' ).

How do I check if page ID matches ID in array during loop?

I've written a custom query in WordPress that loops through 4 different page ID's and pulls out the page titles. What I need to do is check if the page being viewed is one of those ID's and if that's the case don't display that specific title. I know I basically need to do a check against the current page ID and the ID's in the array as it loops, but how would I go about doing that?
<?php
$service_args = array (
'post_type'=> 'page',
'post__in' => array(87,106,108,110), // The page ID's
'orderby' => 'ID',
'order' => 'ASC'
);
$servicesquery = new WP_Query( $service_args );
if ( $servicesquery->have_posts() ) {
while ( $servicesquery->have_posts() ) {
$servicesquery->the_post();
?>
<h4><?php echo the_title(); ?></h4>
<?php } wp_reset_postdata(); ?>
You can get the current page/post Id using <?php get_the_ID(); ?>. Find current page id and exclude it from the array that you are preparing.
$posts_array = array(87,106,108,110);
$current_page_id = get_the_ID();
if ( ($key = array_search($current_page_id, $posts_array)) !== false) {
unset($posts_array[$key]);
}
$service_args = array (
'post_type'=> 'page',
'post__in' => $posts_array, // The page ID's array
'orderby' => 'ID',
'order' => 'ASC'
);
$servicesquery = new WP_Query( $service_args );
if ( $servicesquery->have_posts() ) {
while ( $servicesquery->have_posts() ) {
$servicesquery->the_post();
?>
<h4><?php echo the_title(); ?></h4>
<?php
}
wp_reset_postdata();
?>
Try declaring the page id outside of the while loop, like this:
var thisPageId = get_the_ID();
while ( $servicesquery->have_posts() ) {
if ( $servicesquery->post->ID != thisPageId ) {
echo the_title();
}
}
I managed to solve my problem with the help of this post by using array_diff to check against the ID's: https://wordpress.stackexchange.com/questions/108697/use-post-in-and-post-not-in-together
$this_post = $post->ID; // Get the current page ID
$exclude = array($this_post); // Exclude the current page ID from loop
$include = array(87,104,106,108,110); // ID's of pages to loop through
$service_args = array (
'post_type' => 'page',
'post__in' => array_diff($include, $exclude),
'orderby' => 'ID',
'order' => 'ASC'
);

Categories