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;
        }
    }
});

这段代码做的事情也很简单:

  1. 读取当前访问路径
  2. 判断是不是 /archives/数字
  3. 提取数字作为文章 ID
  4. get_permalink($post_id) 获取文章当前正式链接
  5. 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 自动跳到最新正式地址