WordPress版本低于5.5的话怎么定制sitemap输出

WordPress5.5版本开始内核支持sitemap的输出了,但如果你的主机还不方便升级到这个版本以上,或者没有升级的想法,那怎么办?

常规的可以安装WordPress关于sitemap的插件,比如XML Sitemaps, 但既然WordPress已经集合到内核了,更好的方案应该是从新版中提取相应的程序,这样将来如果升级了,相关程序也能更好的过渡过来。

让我们从大于WordPress5.5版本中来看它是如何实现sitemap的。

在WordPress文件夹所有php的文件中全局搜索sitemap,发现总共有13个文件包含该关键词:

  • wp-setting.php 用于加载所有sitemap用到的文件
  • wp-includes\canonical.php 用于处理sitemap的固定链接分页等问题
  • wp-includes\default-filters.php 在init勾子中初始化加载sitemap,如果是sitemap地址则显示sitemap
  • wp-includes\sitemapsphp sitemap相关的一些函数
  • wp-includes\sitemaps\class-wp-sitemaps-index.php sitemap索引页实现类
  • wp-includes\sitemaps\class-wp-sitemaps-provider.php 具体sitemap实现的抽象类
  • wp-includes\sitemaps\class-wp-sitemaps-registry.php sitemap注册类,决定在sitemap中输出哪些类型的内容
  • wp-includes\sitemaps\class-wp-sitemaps-renderer.php sitemap渲染类,用于最终输出sitemap的xml文件内容
  • wp-includes\sitemaps\class-wp-sitemaps-stylesheet.php sitemap样式类,使用xsl美化浏览器中看到的sitemap外观
  • wp-includes\sitemaps\class-wp-sitemaps.php sitemap工厂类,在init中初始化时用到
  • wp-includes\sitemaps\providers\class-wp-sitemaps-posts.php 各种post的sitemap实现类,继承自class::WP_Sitemaps_Provider
  • wp-includes\sitemaps\providers\class-wp-sitemaps-taxonomies.php 所有taxonomy的sitemap实现类,继承自class::WP_Sitemaps_Provider
  • wp-includes\sitemaps\providers\class-wp-sitemaps-users.php user的sitemap实现类,继承自class::WP_Sitemaps_Provider

通过这些文件,我们可以了解到,要加载sitemap功能,大致分三步:

  1. 加载sitemap相关的所有文件
  2. 在init勾子中加载初始化sitemap的代码
  3. 处理sitemap页可能的链接问题

以下如果你有需要可以跟着我一起来分步完成sitemap的集成。

加载sitemap相关的所有文件

在主题包下新建文件夹,命名为sitemap,将wp-includes\sitemaps.phpwp-includes\sitemamps文件夹,一起复制到sitemap文件夹中。不知道从哪里获取文件的话,本文以5.7版本为例,可以从官方下载页面下载WordPress压缩包,解压后按路径获取。

之后在sitemap下新建文件load.php并打开,添加如下代码

1
2
3
4
5
6
7
8
9
10
require_once __DIR__.'/sitemaps.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-index.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-provider.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-registry.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-renderer.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-stylesheet.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-posts.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-taxonomies.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-users.php';

随后,在主题的functions.php加入如下代码

1
2
3
4
5
6
/**
* WP版本升级到5.5以上就不需要了,内置sitemap了,所以检测代码版本,低于5.5才加载sitemap相应的文件
*/
if(version_compare(get_bloginfo('version'),'5.5', '<')) {
require_once __DIR__.'/sitemap/load.php';
}

在init勾子中加载初始化sitemap的代码

打开sitemap\load.php添加入如代码

1
add_action( 'init', 'wp_sitemaps_get_server' );

处理sitemap页可能的链接问题

WordPress在页面中查询paged分页的时候,会自动在固定链接上添加page/xxx这样的地址,如果当前地址没有page,则会自动跳转至page页,而在sitemap中,我们不需要这个设定,所以需要更改。在WordPress5.5之后的版本中,该问题已得到修正,在之前的版本中我们只好自己修正它。 打开sitemap\load.php添加入如代码

1
2
3
4
5
6
7
add_filter('redirect_canonical',function($redirect_url, $requested_url){
//判断是否是sitemap页
if(!empty(get_query_var('sitemap'))) {
$redirect_url=$requested_url;
}
return $redirect_url;
},10,2);

然后再补上处理xml文件所需的esc_xml函数,该函数是WordPress5.5版本为sitemap新增加的函数,所以需要从wp-includes\formatting.php中获取,大约是在4549行开始。在sitemap文件夹下新建esc_xml.php,然后复制esc_xml的函数进来后保存。随后,在sitemap/load.php中添加如下代码

1
require_once __DIR__.'/esc_xml.php';

这样就在旧版的WordPress中也集成了sitemap功能,另外关于sitemap的定制,则直接参考之前的文章【如何定制WordPress的Sitemap输出】

完整的sitemap/load.php代码示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
require_once __DIR__.'/esc_xml.php';//解决xml解析函数缺失,5.5版本才新加入
require_once __DIR__.'/sitemaps.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-index.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-provider.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-registry.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-renderer.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps-stylesheet.php';
require_once __DIR__.'/sitemaps/class-wp-sitemaps.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-posts.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-taxonomies.php';
require_once __DIR__.'/sitemaps/providers/class-wp-sitemaps-users.php';

add_action( 'init', 'wp_sitemaps_get_server' );

//解决sitemap中的分页固定链接page问题
add_filter('redirect_canonical',function($redirect_url, $requested_url){
//判断是否是sitemap页
if(!empty(get_query_var('sitemap'))) {
$redirect_url=$requested_url;
}
return $redirect_url;
},10,2);