需求背景
在 WordPress 网站开发中,有时我们会在首页主循环之外(例如通过自定义区块或小工具)单独调用并展示网站的置顶文章。为了避免首页出现两块完全相同的置顶文章列表,我们需要将主循环中默认显示在最新文章前面的置顶文章排除掉。
解决方案
过去,你可能见过使用 query_posts() 函数来修改主查询以排除置顶文章的方法。但请注意,强烈不推荐使用 query_posts(),因为它会完全替换主查询,很容易导致分页功能出错、插件兼容性问题以及其他难以排查的副作用。
正确且推荐的方法是使用 WordPress 提供的 pre_get_posts 动作钩子。它允许你在主查询执行之前,安全地修改其参数。
核心代码
将以下代码添加到当前主题的 functions.php 文件中:
function exclude_sticky_posts($query) {
// 确保只在前端的主查询中执行
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// 仅在首页应用此规则
if ( $query->is_home() ) {
// 设置忽略置顶文章,让它们按正常顺序排列
$query->set( 'ignore_sticky_posts', 1 );
}
}
add_action( 'pre_get_posts', 'exclude_sticky_posts' );
代码详解
is_admin():检查是否在 WordPress 管理后台,避免影响后台的文章列表。$query->is_main_query():确保只修改网站的主查询,不影响侧边栏小工具、菜单等其他查询。$query->is_home():指定此规则仅作用于网站首页。$query->set( 'ignore_sticky_posts', 1 ):这是关键参数。将其设置为1或true后,WordPress 将不再把置顶文章“粘”到列表最前面,而是让所有文章(包括原置顶文章)都按照正常的发布时间、菜单顺序或其他排序参数进行排列。
扩展应用
如果你需要在其他页面(如分类归档页、标签页或搜索页)也排除置顶文章,只需修改条件判断语句即可。例如,要排除分类页面中的置顶文章:
if ( $query->is_category() ) {
$query->set( 'ignore_sticky_posts', 1 );
}
你也可以组合多个条件,或将其应用于所有归档页面:
// 在首页和所有归档页面(分类、标签、作者、日期)排除置顶文章
if ( $query->is_home() || $query->is_archive() ) {
$query->set( 'ignore_sticky_posts', 1 );
}
注意事项
- 此方法仅影响文章的显示顺序。置顶文章本身的状态(Sticky)并未改变,它们在其他符合条件的主查询中(如果未设置
ignore_sticky_posts)依然会置顶显示。 - 如果你在首页之外的其他地方单独调用置顶文章,通常使用的是
WP_Query或get_posts,在这些查询中你可以通过设置'post__in' => get_option( 'sticky_posts' )等参数来精确控制,不会受上述主查询修改的影响。 - 修改主题的
functions.php文件前,建议先创建子主题,或在修改前备份原文件。