本文约 3,447 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:三个”设置不管用”的瞬间
第一个:后台”阅读设置”里写了每页 10 篇,分类页却只显示 6 篇。第二个:想让摘要短一点,改了主题的 the_excerpt() 调用,结果有的文章摘要是一整段,有的只有一句。第三个:分页只有”上一页/下一页”两个链接,想显示页码数字却不知道从哪加。
第一个问题多半是主题(或插件)用 pre_get_posts 改过主查询;第二个是 the_excerpt() 的行为差异——有手动摘要时原样输出,excerpt_length 过滤器只在自动生成摘要时生效;第三个则是模板里没有调用分页函数或只调用了 posts_nav_link()。理解这三点,列表页就能按自己的意图来。
原理分析:查询、摘要、分页三段各自独立
查询段:WordPress 在解析请求时生成主查询 WP_Query,posts_per_page 来自”阅读设置”。任何挂在 pre_get_posts 上的回调都能在 SQL 执行前修改这个查询对象,所以”设置与实际不符”基本都是被改过。注意 pre_get_posts 会对所有查询生效,必须加 is_main_query() 判断,否则后台、小工具、REST 请求都会被牵连。
摘要段:the_excerpt() 先看文章有没有手动填写的”摘要”字段,有就原样输出(仍会经过 the_excerpt 过滤器与 wpautop);没有则截取正文前若干词,词数由 excerpt_length 过滤器控制,结尾由 excerpt_more 过滤器控制。所以”改了长度没变化”往往是那些文章本来就有手动摘要。
分页段:the_posts_pagination() 内部调用 paginate_links(),支持 mid_size、end_size、prev_text、next_text、screen_reader_text 等参数,输出带 nav 包裹的页码链接,比老的 posts_nav_link() 可控得多。
| 现象 | 检查点 |
|---|---|
| 归档页数量与设置不一致 | pre_get_posts / posts_per_page |
| 摘要长度不统一 | 是否填写了手动摘要 |
| 只有上下页没有页码 | 是否用了 the_posts_pagination |
| 分页 404 | 固定链接未刷新 / paged 变量未处理 |
| 后台也被影响 | is_main_query() 判断缺失 |
保姆级实操
- 确认当前查询参数:临时打印
$query->get( 'posts_per_page' )(仅本地调试),确认是否被改过。 - 搜索主题的
pre_get_posts:找到后在其之上叠加你的规则,或用自己的回调覆盖,注意优先级。 - 限定生效范围:只改前台主查询,跳过后台、搜索与 feeds。
- 统一摘要长度:同时处理
excerpt_length与excerpt_more;对有手动摘要的文章,用wp_trim_words()强制截断以保证列表整齐。 - 换分页函数:把模板里的
posts_nav_link()换成the_posts_pagination(),并配置页码数量。 - 列表布局用 CSS Grid:卡片式列表比浮动布局更好维护,配合
get_template_part抽离单项模板。
<?php
// 分类归档页单独设置每页数量,其余保持后台设置
add_action( 'pre_get_posts', 'mimangfei_archive_per_page' );
function mimangfei_archive_per_page( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 12 );
}
}
<?php
// 摘要:自动生成的截断到 80 个词,结尾改成省略号
add_filter( 'excerpt_length', function () {
return 80;
} );
add_filter( 'excerpt_more', function () {
return '…';
} );
// 手动摘要也统一长度,避免列表长短不一
add_filter( 'get_the_excerpt', 'mimangfei_uniform_excerpt', 20 );
function mimangfei_uniform_excerpt( $excerpt ) {
if ( is_admin() ) {
return $excerpt;
}
return wp_trim_words( wp_strip_all_tags( $excerpt ), 80, '…' );
}
<?php
// archive.php:分页 + 单项模板抽离
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/content', get_post_format() );
endwhile;
the_posts_pagination( array(
'mid_size' => 2,
'end_size' => 1,
'prev_text' => __( '上一页', 'lumen-mimangfei' ),
'next_text' => __( '下一页', 'lumen-mimangfei' ),
'screen_reader_text' => __( '文章导航', 'lumen-mimangfei' ),
) );
else :
get_template_part( 'template-parts/content', 'none' );
endif;
常见踩坑
pre_get_posts没加is_main_query(),导致后台文章列表、站内搜索结果数量一起被改。- 摘要长度改了没效果,因为文章本身就填了手动摘要,
excerpt_length不参与。 is_home()与is_front_page()混用:静态首页下is_home()指向的是”文章页”,不是首页。- 分页第二页 404,实际是固定链接结构改过但没刷新重写规则。
- 案例:某站分类页只显示 6 篇,改”阅读设置”毫无反应。排查发现主题为首页轮播注册了一个
pre_get_posts,里面写了if ( $query->is_home() ),但没判断is_main_query(),导致侧边栏”最新文章”小工具也变成 6 篇。补全判断并改为只对特定分类生效后恢复正常。 - 用
query_posts()改查询,会覆盖主查询并引发分页错乱(应改用pre_get_posts)。 - 摘要里保留 HTML 标签导致截断后出现未闭合标签,列表结构崩坏。
总结
列表页的三段各自独立:数量看 pre_get_posts(务必加 is_main_query()),摘要看 excerpt_length 与手动摘要的差别,分页看是否用 the_posts_pagination()。判断标准是”改完一个参数,只在目标归档页生效,后台与搜索不受影响”。行动清单:① 先查主题是否改过主查询;② 统一手动与自动摘要的长度;③ 换用带页码的分页函数;④ 列表结构用 Grid;⑤ 改完刷新固定链接。延伸阅读 lumen-mimangfei 主题首页布局、lumen-mimangfei 主题特色图片设置 与 WordPress 模板层级。
