如何通过WP_Query参数按分类法数量倒序排列自定义文章类型?
解决方案:按Localisation分类的酒店数量倒序展示Hotels
好问题!直接用WP_Query的默认参数没办法直接实现这个需求,但我们可以通过两种常见方式来达成你的目标——取决于你是想按地区分类分组展示酒店,还是把所有酒店按所属地区的酒店数量排序后统一展示。
场景1:按地区分类分组展示(分类按酒店数量倒序)
这是最直观的方式:先获取所有带有酒店的Localisation分类,按分类下的酒店数量倒序排列,然后逐个查询每个分类下的酒店并展示。
// 获取按酒店数量倒序排列的Localisation分类 $localisations = get_terms(array( 'taxonomy' => 'localisation', 'hide_empty' => true, // 只保留有酒店的分类 'orderby' => 'count', 'order' => 'DESC' )); if (!empty($localisations) && !is_wp_error($localisations)) { foreach ($localisations as $localisation) { // 输出分类名称及酒店数量 echo '<h2>' . esc_html($localisation->name) . ' (' . $localisation->count . ' 家酒店)</h2>'; // 查询当前分类下的所有酒店 $hotel_query = new WP_Query(array( 'post_type' => 'hotels', 'posts_per_page' => -1, // 显示该分类下所有酒店 'tax_query' => array( array( 'taxonomy' => 'localisation', 'field' => 'term_id', 'terms' => $localisation->term_id ) ) )); if ($hotel_query->have_posts()) { echo '<ul class="hotel-list">'; while ($hotel_query->have_posts()) { $hotel_query->the_post(); echo '<li><a href="' . esc_attr(get_permalink()) . '">' . esc_html(get_the_title()) . '</a></li>'; } echo '</ul>'; wp_reset_postdata(); // 重置查询上下文 } } }
这种方式逻辑清晰,易于维护,适合需要按地区分组展示的场景。
场景2:所有酒店按所属地区的酒店数量倒序排列
如果你希望把所有酒店文章直接按其所属地区的酒店总数倒序排列(比如地区A有10家酒店,那地区A的所有酒店都排在地区B(5家酒店)的酒店前面),就需要通过自定义SQL过滤器来修改WP_Query的排序规则。
// 自定义排序规则:按所属Localisation的酒店数量倒序 add_filter('posts_orderby', 'sort_hotels_by_localisation_count', 10, 2); function sort_hotels_by_localisation_count($orderby, $query) { // 只针对我们的酒店查询生效,避免影响其他查询 if (!is_admin() && $query->get('post_type') === 'hotels' && $query->get('sort_by_localisation_count')) { global $wpdb; // 按分类的文章数量倒序,其次按酒店发布时间倒序 $orderby = "{$wpdb->term_taxonomy}.count DESC, {$wpdb->posts}.post_date DESC"; } return $orderby; } // 关联分类相关数据表,让排序规则生效 add_filter('posts_join', 'join_localisation_taxonomy_table', 10, 2); function join_localisation_taxonomy_table($join, $query) { if (!is_admin() && $query->get('post_type') === 'hotels' && $query->get('sort_by_localisation_count')) { global $wpdb; $join .= " INNER JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id "; $join .= " INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id "; $join .= " WHERE {$wpdb->term_taxonomy}.taxonomy = 'localisation' "; } return $join; } // 执行WP_Query查询 $hotel_query = new WP_Query(array( 'post_type' => 'hotels', 'posts_per_page' => -1, 'sort_by_localisation_count' => true, // 自定义参数,触发上面的过滤器 'tax_query' => array( array( 'taxonomy' => 'localisation', 'operator' => 'EXISTS' // 只查询带有Localisation分类的酒店 ) ) )); // 循环输出酒店 if ($hotel_query->have_posts()) { while ($hotel_query->have_posts()) { $hotel_query->the_post(); // 获取当前酒店所属的地区名称 $localisation_terms = get_the_terms(get_the_ID(), 'localisation'); $localisation_name = !empty($localisation_terms) ? esc_html($localisation_terms[0]->name) : '未指定地区'; echo '<div class="hotel-item">'; echo '<h3>' . esc_html(get_the_title()) . '</h3>'; echo '<p>所属地区:' . $localisation_name . '</p>'; echo '</div>'; } wp_reset_postdata(); } // 移除过滤器,避免影响后续其他查询 remove_filter('posts_orderby', 'sort_hotels_by_localisation_count'); remove_filter('posts_join', 'join_localisation_taxonomy_table');
这种方式需要修改WP_Query的底层SQL,适合需要统一排序所有酒店的场景。
内容的提问来源于stack exchange,提问作者Vincent Decaux
相关产品推荐
相关产品推荐

