profileName: youpingfang postId: 319 postType: post categories:
- 1
最近遇到一个挺实际的小问题。我有一些 WordPress 文章,标题是中文,文章链接也是中文 slug。比如一篇文章的正式链接长这样:
https://an.lovescie.com/大白话讲解:数据预处理/
浏览器里看着没问题,但真正复制出来以后放到 b 站评论区,URL 会变成一长串编码(说明 b 站评论区有点让人恶心了)
https://an.lovescie.com/%e5%a4%a7%e7%99%bd%e8%af%9d%e8%ae%b2%e8%a7%a3%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%a2%84%e5%a4%84%e7%90%86/
这本身是正常的,因为 URL 里中文需要被编码。但问题来了:我想把链接发到 B 站评论区,评论区对 URL 的处理并不总是稳定。带中文的链接容易变得很丑,甚至出现乱码、截断、识别异常。
这其实是一个很小的细节,但对经常在外部平台分享文章的人来说挺有用。中文 URL 对搜索和阅读是友好的,但在一些评论区、App、聊天环境里并不总是稳定。用文章 ID 做一层短链接,再重定向到正式链接,是一个比较稳的折中方案。以后外部平台发短链接,站内保留中文链接。两边都舒服。
最开始的想法:用文章 ID
WordPress 每篇文章都有一个固定 ID。比如这篇文章的 ID 是 252,那理论上可以用一个更短、更干净的链接:
https://an.lovescie.com/archives/252
这个链接全是英文和数字,发到 B 站、微博、评论区、聊天软件里都更稳定,不会出现中文编码问题。
但问题是,我当前站点的正式链接并不是 /archives/252 这种结构,而是文章标题链接。所以直接访问这个旧格式,可能会 404。
这时候就需要做一个自动重定向。
目标
我想实现的效果很简单:
用户访问:
https://an.lovescie.com/archives/252
网站自动跳转到文章 ID 为 252 的当前正式链接:
https://an.lovescie.com/大白话讲解:数据预处理/
这样我以后在外部平台只需要发短链接:
https://an.lovescie.com/archives/252
不需要管中文 URL 编码,也不需要每篇文章手动添加跳转规则。
方法一:用 Redirection 插件,一条正则规则搞定
下载Redirection 插件,新建一条重定向规则: 源 URL:
^/archives/([0-9]+)/?$
目标 URL:
https://an.lovescie.com/?p=$1
然后开启正则匹配,状态码选择 301。
这里的意思是:
/archives/252
会被识别成:
?p=252
而 WordPress 原生支持通过 ?p=文章ID 访问文章,并通常会自动跳转到当前正式 permalink。
比如:
https://an.lovescie.com/?p=252
会跳到:
https://an.lovescie.com/大白话讲解:数据预处理/
这个方法的优点是简单,而且 Redirection 插件还能统计这些旧链接被访问了多少次。
方法二:用代码自动处理
如果你想少装插件,也可以把下面这段代码放到主题的 functions.php,或者用 Code Snippets 插件添加:
add_action('template_redirect', function () {
$path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
if (preg_match('#^archives/(\d+)$#', $path, $matches)) {
$post_id = (int) $matches[1];
$url = get_permalink($post_id);
if ($url) {
wp_redirect($url, 301);
exit;
}
}
});
这段代码做的事情也很简单:
- 读取当前访问路径
- 判断是不是
/archives/数字 - 提取数字作为文章 ID
- 用
get_permalink($post_id)获取文章当前正式链接 - 用
301跳转过去
这样以后所有类似链接都会自动生效:
https://an.lovescie.com/archives/252
https://an.lovescie.com/archives/100
https://an.lovescie.com/archives/999
只要对应文章存在,就会自动跳到正式链接。
手动一个个加?
当然,也可以每篇文章都手动添加一条重定向,比如:
/archives/252 -> /大白话讲解:数据预处理/
但这太麻烦了。
文章多了以后,维护成本会越来越高。而文章 ID 本身就是稳定的,所以最好的方式是利用这个规律,让系统自动完成映射。
也就是说,我真正需要的不是一堆重定向记录,而是一条通用规则:
/archives/{文章ID} -> get_permalink(文章ID)
最后的方案
我最后更倾向于保留这种外部分享格式:
https://an.lovescie.com/archives/252
总结这样做的优点: - 全英文数字,不怕中文乱码 - 短,适合发评论区 - 和 WordPress 文章 ID 对应,容易管理 - 即使以后文章标题或 slug 改了,链接也不用改 - 可以通过 301 自动跳到最新正式地址