当使用 WordPress 写文章时,如果单篇文章过长,可以考虑进行分页处理。WordPress 内置了一个分页的代码,只需要在文本书写页面、需要分页的地方输入<!--nextpage-->
即可。
但是问题来了,通常我们给 WordPress 进行了网址伪静态处理,例如给文章和页面加了 .html
后缀,例如将 /2021/11/09/new-post 的文章修饰成 /2021/11/09/new-post.html 。但如果该文章进行了分页处理,那么,第二页通常就会变成 /2021/11/09/new-post.html/2/ (或 /2021/11/09/new-post.html/2)这种格式,而改变了后缀为 .html 的形式。我们需要的第二页是类似于 /2021/11/09/new-post-2.html
这种格式。
如何做呢?
需要修改重写规则。
知更鸟曾写过一篇关于这个问题的文章,但是由于分页设置的伪静态操作涉及到很多具体环境,无法形成统一的公式,所以只能具体情况具体分析具体解决了。本文主要是针对采用 /%year%/%monthnum%/%postname%.html
这种格式的固定连接的用户,也就是 /年/月/文章名字.html
这种格式。
本文是在知更鸟文章中代码的基础上进行的修改操作。
首先,你应当了解自己 WordPress 系统中固定连接(伪静态链接重写规则)修改的大致情况。可以通过向主题 functions.php 中添加如下代码查看:
- add_filter( 'rewrite_rules_array', 'show_rewrite_rules' );
- function show_rewrite_rules( $rules ) {
- echo nl2br( var_export( $rules, true ) );
- die;
- }
打开后台 /wp-admin/options-permalink.php
页面查看,复制里面的内容,取消上述代码。
本文禁止住转载。任何形式转载请联系作者(时光在路上 www.timezls.com)。时光在路上保留所有权利
你会有如下发现,控制 .html 固定连接显示成 .html/2/ 类似格式规则的代码主要有以下几个(可能你的情况与下列有不同):
1. '([0-9]{4})/([0-9]{1,2})/([^/]+).html(?:/([0-9]+))?/?$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]&page=$matches[4]', 2. '[0-9]{4}/[0-9]{1,2}/[^/]+.html/([^/]+)/?$' => 'index.php?attachment=$matches[1]', 3. '(.?.+?).html(?:/([0-9]+))?/?$' => 'index.php?pagename=$matches[1]&page=$matches[2]',
一眼就可以看出第一行是我们所需要修改的。
其实第2个也是需要修改的,下面会讲到。
本文禁止住转载。任何形式转载请联系作者(时光在路上 www.timezls.com)。时光在路上保留所有权利
重写规则需要修改成如下格式:
'([0-9]{4})/([0-9]{1,2})/([^/]+)-([0-9]+).html$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]&page=$matches[4]'
而且,为了防止重复链接指向同一文章,我们也需要移除原有的重写规则:([0-9]{4})/([0-9]{1,2})/([^/]+).html(?:/([0-9]+))?/?$
。因为移除了该规则,导致正常文章无法显示,所以要新增规则:
'([0-9]{4})/([0-9]{1,2})/([^/]+).html$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]'
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
另外,也应把 [0-9]{4}/[0-9]{1,2}/[^/]+.html/([^/]+)/?$
移除,这个是查看附件的页面链接,反正也没啥用。多了这个反而会出现查看 /年/月/文章名字.html/2/
的时候301跳转到 /年/月/文章名字.html/2/1
的情况,默认找附件去鸟~ 把它移除,那么就会直接返回404,而不会自动301跳转。
代码如下:
本文禁止无授权转载 - 时光在路上 www.timezls.com 保留所有权利
- // 添加分页处理规则,适合 /%year%/%monthnum%/%postname%.html 分页链接修正
- class Rewrite_Inner_Page_Links_id{
- function __construct(){
- if( !is_admin() || defined( 'DOING_AJAX' ) ) :
- add_filter( 'wp_link_pages_link', array( $this, 'inner_page_link_format' ), 10, 2 );
- add_filter( 'redirect_canonical', array( $this, 'cancel_redirect_for_paged_posts' ), 10, 2 );
- endif;
- if( is_admin() ) :
- add_filter( 'rewrite_rules_array', array( $this, 'pagelink_rewrite_rules' ) );
- register_activation_hook( __FILE__, array( $this, 'flush_rewrite_rules' ) ) ;
- register_deactivation_hook( __FILE__, array( $this, 'flush_rewrite_rules' ) );
- endif;
- }
- function flush_rewrite_rules(){
- flush_rewrite_rules();
- }
- // 修改post分页链接的格式,替换
- function inner_page_link_format( $link, $number ){
- if( $number > 1 ){
- if( preg_match( '%<a href=".*\.html\/\d*\/"%', $link ) ){
- $link = preg_replace( "%(\.html)\/(\d*)%", "-$2$1", $link );
- }
- }
- return $link;
- }
- // 为新的链接格式增加重定向规则,移除原始分页链接的重定向规则,防止重复收录
- function pagelink_rewrite_rules( $rules ){
- foreach ($rules as $rule => $rewrite) {
- if ( $rule == '([0-9]{4})/([0-9]{1,2})/([^/]+).html(?:/([0-9]+))?/?$' //正常页面 /%year%/%monthnum%/%postname%.html
- || $rule == '[0-9]{4}/[0-9]{1,2}/[^/]+.html/([^/]+)/?$' // 这个是查看附件的页面,没啥用,多了反而麻烦,见文章中的解释
- ) {
- unset($rules[$rule]);
- }
- }
- $new_rule['([0-9]{4})/([0-9]{1,2})/([^/]+)-([0-9]+).html$'] = 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]&page=$matches[4]';
- $new_rule['([0-9]{4})/([0-9]{1,2})/([^/]+).html$'] = 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]';
- return $new_rule + $rules; //这里的顺序很重要,先$new_rule 之后才是原来的$rules,从上到下读取,否则设置无效,404页面
- }
- // 禁止WordPress将页面分页链接跳转到原来的格式
- function cancel_redirect_for_paged_posts( $redirect_url, $requested_url ){
- global $wp_query;
- if( is_single() && $wp_query->get( 'page' ) > 1 ){
- return false;
- }
- return true;
- }
- }
- new Rewrite_Inner_Page_Links_id();
以上就是主要代码,添加到主题的 functions.php 中。
代码分享链接: pan.baidu.com/s/1v9UnNKdRRtYlR71wGStJVg 提取码: 31ay
。
更简单的解决方式
还有一种更简单一些方法。大概思路是:在原有重写规则的基础上加入新的分页面格式的重写规则,不去改变原有的重写规则。那么,如何处置多网址指向同一页面的情况?即 /年/月/文章名字.html/2/
和 /年/月/文章名字-2.html
都指向同一页面。我们需要做的是禁止查看或抓取 /年/月/文章名字.html/2/
这个页面即可。这个操作可以在服务器端设置,而不用理会 WordPress 系统怎样设置了重写规则。
主要代码如下:
- //添加分页重写规则
- function add_custom_post_rewrite_rules( $rules ) {
- $custom_rules = array(
- '([0-9]{4})/([0-9]{1,2})/([^/]+)-([0-9]+).html$' => 'index.php?year=$matches[1]&monthnum=$matches[2]&name=$matches[3]&page=$matches[4]',
- );
- $rules = array_merge( $custom_rules, $rules ); //合并数组,注意先后顺序,自定义$custom_rules在前,原来的规则$rules在后,否则无效
- return $rules;
- }
- add_filter( 'post_rewrite_rules', 'add_custom_post_rewrite_rules' );
- //修改输出的分页链接格式
- function custom_wp_link_pages( $args = '' ) {
- $args .= ( $args ? '&' : '' ) . 'echo=0'; // 三目运算符和echo设置,关于参数echo,下面有解释
- $links = wp_link_pages( $args );
- $links = preg_replace_callback( '|([0-9]{4}/[0-9]{1,2}/)([^/]+)(\.html)(/)([0-9]+)|', 'custom_page_link', $links );
- echo $links;
- }
- function custom_page_link($matches) {
- return $matches[1].$matches[2].'-'.$matches[5].$matches[3];
- }
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
而后,你需要在自己的主题文件中调用自定义函数 custom_wp_link_pages()
。
文章分页的时候,一般的主题都会在 <?php the_content(); ?>
(输出文章内容)的下面有这样的语句 <?php wp_link_pages(); ?>
(或者是已经添加了不同参数的类似输出语句),例如在主题模板文件 single.php 中能找到上述语句。这时需要做的就是把 wp_link_pages()
改为自定义函数 custom_wp_link_pages()
。
如果你想对分页输出样式进行修饰美化,可以改成类似于如下形式的代码(点击查看):
- <?php
- custom_wp_link_pages('before=<div class="page-links"><p>分页阅读:</p>&after=</div>&next_or_number=number&link_before=<span>&link_after=</span>');
- ?>
或者:
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
- <?php
- custom_wp_link_pages('before=<strong>&after=</strong>&next_or_number=next&previouspagelink=上一页&nextpagelink=');
- echo " ";
- custom_wp_link_pages('before=<span class="wp-pagenavi">&after=</span>&next_or_number=number');
- echo " ";
- custom_wp_link_pages('before=<strong>&after=</strong>&next_or_number=next&previouspagelink= &nextpagelink=下一页');
- ?>
具体样式可根据需要自行修改。本文末尾提供了其中的参数和相关解释。
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
最后的步骤,禁止出现 /年/月/文章名字.html/2/
这种格式,可以将其在服务器端设置成返回 404。以 Windows IIS 服务器举例,设置代码如下:
- <configuration>
- <system.webServer>
- <rewrite>
- <rules>
- <rule name="no such url found" stopProcessing="true">
- <match url="(.*)" ignoreCase="true" />
- <conditions logicalGrouping="MatchAny">
- <add input="{PATH_INFO}" pattern="^([0-9]{4}\/[0-9]{1,2}\/)([^\/]+).html\/[0-9]" />
- </conditions>
- <action type="CustomResponse" statusCode="404" subStatusCode="0" statusReason="File Not Found" statusDescription="The requested file was not found." />
- </rule>
- </rules>
- </rewrite>
- </system.webServer>
- </configuration>
---- 附:
wp_link_pages( string|array $args = '' )
的解释:
基本用法:
- <?php
- $defaults = array(
- 'before' => '<p>' . __('Pages:') ,
- 'after' => '</p>',
- 'link_before' => '',
- 'link_after' => '',
- 'next_or_number' => 'number',
- 'separator' => ' ',
- 'nextpagelink' => __('Next page') ,
- 'previouspagelink' => __('Previous page') ,
- 'pagelink' => '%',
- 'echo' => 1
- );
- wp_link_pages( $defaults ); ?>
参数解释:
$args:(string|array)(可选)默认参数的数组或字符串,默认为空: ''
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
- 'before':(string) 字符串类型。添加到每个链接前的HTML或文本,默认是
<p> Pages:
. - 'after':(string) 字符串类型。 显示在每个链接后的HTML或文本,默认是
</p>
. - 'link_before':(string) 字符串类型。显示在锚文本前的HTML或文本,位于
<a>
标签内。默认为空。 - 'link_after':(string) 字符串类型。显示在锚文本后的HTML或文本。默认为空。
- 'aria_current':(string) 字符串类型。aria-current 属性的值。可能的值为
page
、step
、location
、date
、time
、true
、false
。默认为page
。 - 'next_or_number':(string) 字符串类型。表明是否使用分页或页码,有效值有两个可供选择:
number
或next
。默认为number
. - 'separator':(string) 字符串类型。 分页链接之间的文本(如果可用),默认为空格。
- 'nextpagelink':(string) 字符串类型。下一页链接的链接文本,默认为
Next Page
。 - 'previouspagelink':(string) 字符串类型。上一页链接的链接文本,默认为
Previous Page
。 - 'pagelink':(string) 字符串类型。格式化分页页码字符串。参数字符串中的
%
会替换成分页页码。所以Page %
会生成 “Page 1”, “Page 2”, 等等。默认为%
,仅为页码。 - 'echo':(int|bool) 整型或布尔型。选择是要返回结果还是直接输出。可接受的写法包括
1
(或true
)或者0
(或false
),默认为1
(或true
),返回NULL或返回内容。如果设置为 0,则直接输出格式化的HTML。注:不过本文需要格式化的html代码,但是,如果设置成'echo=false'
并不能生效,所以还是 写为'echo=0'
比较稳妥。
本文禁止全文转载。任何形式转载请联系作者(时光在路上 www.timezls.com) Copyright © 2024. All Rights Reserved
上述代码链接:pan.baidu.com/s/14-eKogZhOapXcbxwQ9mvrQ 提取码: gu3w