WooCommerce产品评论汇总栏问题:无法按单个产品统计
Fixing Single Product Review Summary & Refining Your Code
Looks like you're trying to build a WooCommerce product review summary bar, and you're two steps away from getting it perfect! Let's tackle both your issues one by one:
1. The Root Cause of "All Products" Review Count
Your current functions aren't properly targeting the single product ID consistently:
- In
get_review_star_count(), you're using an undefined$product_idvariable (it's not passed into the function, so PHP can't resolve it). - In
get_total_review_star_count(), you're relying on the global$post->ID, which might not always point to the current product in all contexts (like if you're using this in a template part or custom shortcode).
2. Professional Code Refinements & Fixes
We'll rebuild this using WooCommerce's native functions where possible (they're optimized and handle edge cases), add proper parameter passing, cache results to reduce database calls, and clean up the structure for maintainability.
Revised Complete Code
/** * Get total number of approved reviews for a specific product * @param int $product_id ID of the target product * @return int Total reviews count */ function get_product_total_reviews( $product_id ) { // Use WooCommerce's built-in function for accurate review count $product = wc_get_product( $product_id ); if ( ! $product ) return 0; return $product->get_review_count(); } /** * Get number of reviews with a specific star rating for a product * @param int $product_id ID of the target product * @param int $rating Star rating (1-5) * @return int Count of reviews with this rating */ function get_product_rating_count( $product_id, $rating ) { // Validate input to avoid invalid queries if ( ! is_numeric( $rating ) || $rating < 1 || $rating > 5 ) return 0; // Cache results to avoid repeated database calls in the loop static $rating_counts = []; $cache_key = $product_id . '_' . $rating; if ( isset( $rating_counts[$cache_key] ) ) { return $rating_counts[$cache_key]; } $count = get_comments([ 'post_id' => $product_id, 'status' => 'approve', 'post_status' => 'publish', 'post_type' => 'product', 'meta_key' => 'rating', 'meta_value' => $rating, 'count' => true, 'no_found_rows' => true, // Optimize query by skipping unnecessary row count ]); $rating_counts[$cache_key] = $count; return $count; } // Display the review summary bar function display_product_review_summary( $product_id = null ) { // Fallback to current product ID if no ID is provided if ( is_null( $product_id ) ) { global $post; $product_id = $post->ID; } $total_reviews = get_product_total_reviews( $product_id ); if ( $total_reviews === 0 ) { echo '<div class="reviews_bar uk-margin-medium"><p>No reviews yet.</p></div>'; return; } ?> <div class="reviews_bar uk-margin-medium"> <h5><?php esc_html_e( 'Review summary:', 'text-domain' ); ?></h5> <?php for ( $i = 5; $i >= 1; $i-- ) : ?> <?php $rating_count = get_product_rating_count( $product_id, $i ); $percentage = floor( ( $rating_count / $total_reviews ) * 100 ); ?> <div class="bars"> <div class="star_num" data-uk-leader> <?php printf( _n( '%s star', '%s stars', $i, 'text-domain' ), $i ); ?> </div> <div class="star_perc" style="width: <?php echo esc_attr( $percentage . '%' ); ?>"> <?php echo esc_html( $rating_count . ' / ' . $percentage . '%' ); ?> </div> </div> <?php endfor; ?> </div> <?php } // Usage: Call this function in your product template // display_product_review_summary(); // Uses current product ID // OR pass a specific product ID: display_product_review_summary( 123 );
Key Improvements Explained
- Single Product Targeting: Every function accepts a
$product_idparameter, ensuring we always query reviews for the exact product you want. We only fall back to the global$postwhen no ID is explicitly provided. - WooCommerce Native Functions:
wc_get_product()andget_review_count()are maintained by WooCommerce, so they handle edge cases (like product variations, hidden products) better than customget_comments()calls. - Query Optimization: Added
no_found_rowsto speed up comment queries, and used static caching to avoid running the same rating count query multiple times in the loop. - Security: Used
esc_html()andesc_attr()to sanitize output, preventing potential XSS vulnerabilities. - Clean Structure: Split logic into reusable functions, making the code easier to maintain, test, and modify later.
- Edge Case Handling: Added a check for zero reviews to show a friendly message instead of empty bars.
Final Notes
- Replace
text-domainwith your theme/plugin's actual text domain for proper translation support. - Move the inline
style="width: ..."to your CSS file for better separation of concerns (e.g., add a class likestar-percentageand set width via CSS, using inline styles only for dynamic percentage values).
内容的提问来源于stack exchange,提问作者Oussama Bouyardane
相关产品推荐
相关产品推荐

