WordPress程序指定分类内容首页不显示

问题场景

WordPress 首页默认会列出所有最新文章,如果你有些分类是"内部用"或者"日报"性质,不希望它们污染首页排版,就需要主题层面把这些分类的文章从首页 query 里排除掉。比如本站把每天的"60s 资讯"这种刷屏内容单独放一个分类,首页只显示长内容。

WordPress程序指定分类内容首页不显示

解决:pre_get_posts 过滤

WordPress 提供了 pre_get_posts 这个 hook,在查询执行前就介入,可以修改任意 query 的参数。这是处理这类需求的标准做法 —— 比"事后过滤渲染"高效得多,因为 SQL 查询本身就不会捞那些文章。

把下面代码放进主题的 functions.php 或者你的 mu-plugin:

// 首页排除指定分类
function exclude_category_home( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'cat', '-17' ); // 你要排除的分类 ID,负数表示排除
    }
    return $query;
}
add_filter( 'pre_get_posts', 'exclude_category_home' );

核心是 cat 参数支持负数表示排除。多个分类用逗号分隔:'-17,-18,-23'

两个守卫条件别漏

注意上面代码里这两行判断:

if ( $query->is_home() && $query->is_main_query() )

is_home() —— 只针对博客首页生效(不影响分类页、归档页、搜索页)。如果你站点首页是设置成静态页面而不是博客列表,要用 is_front_page()

is_main_query() —— 极其关键!没这个判断,所有侧边栏小工具、相关文章、热门文章这类 secondary query 都会被你过滤,首页 footer 的"最新评论"也会受波及,后果就是页面上一堆"无内容"的小工具空块。

升级版:同时排除多个分类 + 排除 RSS

实际项目里通常要稍微复杂一点。比如:

  • 首页排除"日报"和"通知"两个分类(ID 17 和 18)
  • RSS feed 也要排(否则订阅者天天被刷屏)
  • 站内搜索结果不排(用户可能就是搜这些内容)
function b2be_exclude_categories_from_listings( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    // 首页 / 博客首页 / Feed 都过滤
    if ( $query->is_home() || $query->is_front_page() || $query->is_feed() ) {
        $excluded_cats = [ 17, 18 ];
        $current = $query->get( 'category__not_in', [] );
        $query->set( 'category__not_in', array_merge( $current, $excluded_cats ) );
    }
}
add_filter( 'pre_get_posts', 'b2be_exclude_categories_from_listings' );

这里用了 category__not_in 而不是 cat:

  • cat 只接受字符串,改起来要拼字符串,而且会覆盖之前的设置
  • category__not_in 是数组,可以 merge,更安全,不会覆盖别人(其他插件)已经设的过滤条件

怎么找分类 ID

WordPress 后台 → 文章 → 分类目录,hover 上去看链接,URL 里 tag_ID=17 那个 17 就是分类 ID。或者直接 WP-CLI:

wp term list category --fields=term_id,name,slug,count

顺便:从某个 widget 也想排除

主题/插件提供的"最新文章"、"热门文章"小工具往往用自己的 query,pre_get_posts 也会拦截,这时反而要小心 —— 上面那个 is_main_query() 守卫就是为这个准备的,小工具的 query 不是 main_query,所以不会被影响。

如果你想让某个小工具也排除某分类,得看这个小工具内部用的是 WP_Query 还是 get_posts。如果是常规的 WP_Query,加另一个 hook 单独处理:

// 例如某个"猜你喜欢"小工具,识别它的 query
add_filter( 'pre_get_posts', function( $query ) {
    if ( $query->is_main_query() ) return;
    // 判断这个 secondary query 是哪个小工具发的(通常通过 query vars)
    if ( $query->get( 'widget_id' ) === 'related-posts' ) {
        $query->set( 'category__not_in', [ 17, 18 ] );
    }
});

更激进:直接在主题模板里 query 时就过滤

如果你不想动 pre_get_posts,主题首页模板里直接控制 query 也行:

// 主题的 home.php / front-page.php
<?php
$args = [
    'posts_per_page'      => 10,
    'category__not_in'    => [ 17, 18 ],
    'ignore_sticky_posts' => false,
];
$query = new WP_Query( $args );
while ( $query->have_posts() ) : $query->the_post();
    get_template_part( 'template-parts/content', get_post_format() );
endwhile;
wp_reset_postdata();
?>

不推荐这种做法,因为商业主题升级会覆盖你的模板修改。所有"配置式"的过滤,都尽量做在 pre_get_posts 里 + 放 mu-plugin,主题升级零冲突。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

Vscode使用CDN加速下载

2023-4-7 13:00:15

技术教程

解决网站百度首页不更新的问题

2023-4-10 10:22:29

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索