我试图显示最高评级的职位,cpt与平均评级值。我为此创建了自定义小部件。默认情况下,wp post数据和平均值显示正确,但类似CPT的电影post未显示正确的平均值。我使用以下代码来实现这一点。需要帮助
public function widget( $args, $instance ) {
$title = apply_filters( \'widget_title\', $instance[\'title\'] );
$posttype = $instance[\'posttype\'];
$postsperpage = $instance[\'postsperpage\'];
$postorder = $instance[\'postorder\'];
$avgrt_pos = $instance[\'avgrt_pos\'];
$image = $instance[ \'showimage\' ] ? \'true\' : \'false\';
$avgrt_img = $instance[ \'avgrt_star\' ];
// before and after widget arguments are defined by themes
echo $args[\'before_widget\'];
if ( ! empty( $title ) )
echo $args[\'before_title\'] . $title . $args[\'after_title\'];
global $wpdb, $post;
$results = $wpdb->get_results("SELECT DISTINCT({$wpdb->prefix}comments.comment_post_ID), GROUP_CONCAT({$wpdb->prefix}comments.comment_ID separator \', \') comment_ids FROM {$wpdb->prefix}comments JOIN {$wpdb->prefix}commentmeta ON {$wpdb->prefix}commentmeta.comment_id = {$wpdb->prefix}comments.comment_ID
WHERE {$wpdb->prefix}comments.comment_approved = 1 GROUP BY {$wpdb->prefix}comments.comment_post_ID", ARRAY_A);
foreach($results as $key => $value)
{
$c_post_id = $value[\'comment_post_ID\'];
$comment_ids = $value[\'comment_ids\'];
$res = $wpdb->get_results( "SELECT AVG(`meta_value`) as avg_rate FROM {$wpdb->prefix}commentmeta WHERE `meta_key` = \'rating\' AND `meta_value` != \'\' AND comment_ID IN ($comment_ids) ORDER BY meta_value" );
$results[$key][\'avg_rate\'] = $res[0]->avg_rate;
//var_dump($res);
}
# sort value by high rated
if($postorder==\'DESC\'){
$sortOrder = SORT_DESC;
}else{
$sortOrder = SORT_ASC;
}
# avg stars
if($avgrt_img==\'avgrt_str1\'){
$avgrt_img = \'star-1\';
}elseif($avgrt_img==\'avgrt_str2\'){
$avgrt_img = \'star-2\';
}elseif($avgrt_img==\'avgrt_str3\'){
$avgrt_img = \'star-3\';
}elseif($avgrt_img==\'avgrt_str4\'){
$avgrt_img = \'star-4\';
}elseif($avgrt_img==\'avgrt_str5\'){
$avgrt_img = \'star-5\';
}elseif($avgrt_img==\'avgrt_str6\'){
$avgrt_img = \'star-6\';
}else{
$avgrt_img = \'star-1\';
}
$avg_rate = array_column($results, \'avg_rate\');
array_multisort($avg_rate, $sortOrder, $results);
$top_rated = array();
foreach ($results as $result)
{
if($result[\'avg_rate\'] && $result[\'comment_ids\'] )
{
$top_rated[] = $result[\'comment_post_ID\'];
}
}
$args = array(
\'post_type\' => $posttype,
\'posts_per_page\' => $postsperpage,
\'post__in\' => $top_rated,
\'orderby\' => \'post__in\',
\'post_status\' => \'publish\',
);
$top_rated_posts = new WP_Query( $args );
//var_dump($top_rated_posts);
// The Loop
if ( $top_rated_posts->have_posts() )
{
echo \'<div class="wpcr_top_rated_container"><ul>\';
$i=0;
while ( $top_rated_posts->have_posts() )
{
$top_rated_posts->the_post();
$postid= get_the_ID();
/* grab the url for the full size featured image */
$featured_img_url = get_the_post_thumbnail_url(get_the_ID(),\'thumbnail\');
$get_post_link = get_permalink();
if($image == \'true\'){
if(!empty($featured_img_url)){
$feaimage = \'<a href="\'.esc_url($get_post_link).\'"><img src="\'.esc_url($featured_img_url).\'" alt=""></a>\';
}else {
$feaimage = \'\';
}
}
$topr_desc = get_the_content();
$words = 15;
$more = \' […]\';
$excerpt = wp_trim_words( $topr_desc, $words, $more );
$avgrating = \'<div class="wpcr_aggregate"><a class="wpcr_inline" title=""><span class="wpcr_averageStars_tprt \'.$avgrt_img.\'" data-wpcravg="\'.number_format((float)$results[$i][\'avg_rate\'], 2, \'.\', \'\').\'"></span></a><span class="avg-inline">\'.number_format((float)$results[$i][\'avg_rate\'], 2, \'.\', \'\').\'</span></div>\';
//var_dump($results[$i][\'avg_rate\']);
if($avgrt_pos == \'before\'){
$avg_bef = $avgrating;
}
if($avgrt_pos == \'after\'){
$avg_aft = $avgrating;
}
$output = \'<li>\';
$output .= \'<div class="left">\'.$feaimage.\'</div>\';
$output .= \'<div class="right"><a href="\'.esc_url($get_post_link).\'"><span class="wpcr_title" title="">\'.get_the_title().\'</span></a>\';
$output .= $avg_bef.\'<div class="desc">\'.$excerpt.\'</div>\'.$avg_aft.\'</div></li>\';
echo $output;
$i++;
}
echo \'</ul></div>\';
wp_reset_query();
} else {
echo \'Sorry, no post found.\';
}
echo $args[\'after_widget\'];
}
屏幕截图
SO网友:Tom J Nowell
您的代码使用以下内容:
number_format((float)$results[$i][\'avg_rate\'], 2, \'.\', \'\')
如果我们看看
$i
设置后,我们在循环之前看到:
$i=0;
还有这个:
$i++;
但我看不出在有条件的情况下,这如何以任何方式映射到当前帖子,这意味着并非结果数组中的所有内容都包含在帖子查询中。
相反,不要使用$i
, 使用post ID,并将post ID存储为键。
进一步说明:
这不会按比例扩展,因为帖子数量增加,查询速度会变慢,而评级数量增加,查询速度会变慢。2倍的帖子并不意味着两倍的速度慢,它会变得更快。当没有太多数据时,速度会很快,之后会逐渐停止添加新评分时,只需重新计算帖子的平均评分,并将平均值存储在帖子元中,速度可能会快上千倍,效率也会更高wp_reset_query
这里没有位置。除非你正在使用query_posts
不要使用它。也许你想用wp_reset_postdata
?如果要编写原始SQL查询,请准备语句。不要只在查询字符串中放入变量,这很危险!$wpdb->prepare
如果是你的朋友,请清理这些查询并使其安全。有很多不必要的变量,例如,为什么要使用$output
? 只需回显它们并节省另一个变量的工作量,这是对资源的浪费,在读取和键入时会增加开销,而且没有任何好处$avg_bef
和$avg_aft
仅当选择该位置时才分配,这将生成PHP警告(在PHP 8中,将生成PHP fatals),事先为其分配一个默认值$avg_bef = \'\';
等等,不要只是凭空把它们拉出来