WordPress短代码查询文章时检测函数数据并实现排序分页
WordPress 短代码实现自定义排序全文章分页列表
实现思路
- 排序逻辑直接在
WP_Query的SQL查询层注入,避免拆分两次查询拼接列表导致的分页计数错误、文章重复/遗漏问题,性能也更优 - 分页完全兼容WordPress原生
paged参数,不需要额外自定义分页规则 - 所有输出通过字符串拼接返回,规避短代码直接echo导致的内容位置错乱bug
完整代码
将以下代码放入当前主题的functions.php文件,或者自定义站点功能插件中即可使用:
/** * 注册全文章列表短代码 * 调用方式:在需要展示列表的页面/文章内容中插入 [all_posts_list] */ add_shortcode('all_posts_list', 'mnp_render_all_posts_list'); function mnp_render_all_posts_list() { // 兼容静态首页、普通内页的页码获取 $paged = get_query_var('paged') ? get_query_var('paged') : (get_query_var('page') ? get_query_var('page') : 1); // 临时挂载自定义排序过滤器,仅对本次查询生效 add_filter('posts_clauses', 'mnp_inject_custom_sort_rule', 10, 2); // 文章查询参数 $query_args = [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 10, // 按需修改每页显示文章数量 'paged' => $paged, 'ignore_sticky_posts' => true // 忽略置顶文章,避免打乱自定义排序规则 ]; $custom_query = new WP_Query($query_args); // 查询完成立刻移除过滤器,不影响站点其他查询逻辑 remove_filter('posts_clauses', 'mnp_inject_custom_sort_rule', 10); $output = '<div class="mnp-post-list">'; if ($custom_query->have_posts()) { $output .= '<ul class="mnp-post-items">'; while ($custom_query->have_posts()) { $custom_query->the_post(); // 按需修改此处的文章输出结构,可添加缩略图、发布时间、摘要等内容 $new_tag = mnp_is_new_post() ? '<span class="new-badge">新</span>' : ''; $output .= sprintf( '<li class="mnp-post-item"><a href="%s">%s</a>%s</li>', esc_url(get_permalink()), esc_html(get_the_title()), $new_tag ); } $output .= '</ul>'; // 生成分页导航 $output .= '<div class="mnp-pagination">'; $output .= paginate_links([ 'total' => $custom_query->max_num_pages, 'current' => $paged, 'prev_text' => '上一页', 'next_text' => '下一页', 'type' => 'plain' ]); $output .= '</div>'; wp_reset_postdata(); // 重置全局文章对象,避免干扰页面后续内容 } else { $output .= '<p>暂无已发布文章</p>'; } $output .= '</div>'; return $output; } /** * 注入自定义排序规则:优先展示mnp_is_new_post()返回true的文章,同组内按发布时间倒序 * 注意:如果你的mnp_is_new_post()函数判断新文章的元数据key不是_is_new_post,请对应修改下方meta_key值,保证排序逻辑和原有判断一致 */ function mnp_inject_custom_sort_rule($clauses, $wp_query) { global $wpdb; // 关联文章元表读取新文章标记 $clauses['join'] .= " LEFT JOIN {$wpdb->postmeta} AS mnp_new_flag ON {$wpdb->posts}.ID = mnp_new_flag.post_id AND mnp_new_flag.meta_key = '_is_new_post'"; // 排序规则:带新标记的文章权重为0排最前,其余权重为1排后面,同权重按发布时间倒序 $clauses['orderby'] = "CASE WHEN mnp_new_flag.meta_value = '1' THEN 0 ELSE 1 END ASC, {$wpdb->posts}.post_date DESC"; return $clauses; }
调整说明
- 如果你的
mnp_is_new_post()函数不是通过判断_is_new_post元数据来标记新文章,需要对应修改mnp_inject_custom_sort_rule函数里的关联条件和CASE判断逻辑,确保排序结果和函数判断结果一致 - 文章列表的HTML结构可以根据主题样式需求,修改循环内的输出代码,分页样式可以通过给
.mnp-pagination添加自定义CSS调整 - 不要采用先查询新文章、再查询旧文章拼接数组的方式实现,这种方案需要手动计算分页偏移量,极易出现页码错位、文章重复/遗漏问题,性能也远低于直接修改SQL子句的方案
内容的提问来源于stack exchange,提问作者tiny
相关产品推荐
相关产品推荐

