伪静态规则逐条拆解:{%page%} 为 1 时那段为什么消失
上一篇捋完分类父子关系,这篇直接拆伪静态规则本身。{%page%} 在页码为 1 时不是替换成空字符串,而是整段连同连接符被跳过;分类规则末尾那个斜杠属于规则的一部分,少一个就 404;page=0 能返回第 1 页内容,这个口子要在 Nginx 层堵。附实测对照表。
上一篇把分类父子关系和 URL 生成捋了一遍,结尾说要聊伪静态本身。这篇不绕弯,把四条规则摊开,逐段对着实际请求看。
规则长什么样
文章 {%host%}post/{%id%}.html
页面 {%host%}{%alias%}/
首页 {%host%}page_{%page%}.html
分类 {%host%}{%alias%}_{%page%}/
标签 {%host%}tags/{%alias%}/{%page%}/区别一眼可见:文章和页面规则里没有 {%page%}。文章不分页,独立页面也不分页,用不上。只有列表类才需要分页段。
所以「{%page%} 让整段消失」这个坑,只在首页、分类、标签上出现。
{%page%} 不是变成空,是整段不输出
常见误解:以为页码为 1 时 {%page%} 被替换成空字符串,规则变成 /zblog_/。不是这样。
Z-Blog 生成 URL 时先判断页码,页码为 1 就直接跳过 _{%page%} 这一段,输出干净的 /zblog/。第 2 页才走完整规则,得到 /zblog_2/。
这是段级跳过,不是字符串替换。理解这点才能解释下面两个现象。
现象一:下划线跟着消失
规则写的是 _{%page%},下划线在 {%page%} 前面,它们被当作一个整体。所以第 1 页不是 /zblog_/,而是 /zblog/,下划线也没了。
有人想「我在前面加个固定字符,第一页就带上了」,加完发现第一页依然干净——只要那个字符紧贴 {%page%},就一起被跳过。
现象二:末尾斜杠少一个就 404
分类规则是 {%host%}{%alias%}_{%page%}/,结尾有个斜杠。实测:
| 请求 | 状态 |
|---|---|
/zblog/ | 200 |
/zblog_1/ | 200 |
/zblog | 404 |
/zblog_2/ | 404(该分类仅 1 页) |
斜杠是规则的一部分,不是可选的装饰。Nginx 那边 try_files 找不到文件就交回 PHP,路径对不上规则表自然 404。
顺手发现:/zblog_1/ 和 /zblog/ 同样内容
两条都返回 200,内容一致,但 canonical 都指向 /zblog/。这没问题,重复地址靠 canonical 收敛即可。
真正要注意的是别在站内链到 _1 版本,否则爬虫会多抓一份。
page=0 这个口子
分类规则里 {%page%} 跳过后,/zblog_0/ 这种请求仍会打到后端。PHP 侧把 page=0 当第 1 页处理,返回 200。搜索引擎若抓到,就是又一份重复内容。
处理办法是在 Nginx 层直接拦:if ($request_uri ~ "_0/?$") { return 301 /; },或交给 canonical 兜底。前者更干净。
两条规则怎么写才不出错
- 列表类规则末尾一定带斜杠,页码段紧贴前面的连接符,不要加空格或别的字符。
- 文章、页面规则不要塞 {%page%},它们本来就不分页,塞进去只会生成一堆无效地址。
改完规则记得清缓存重编译模板,然后拿 curl -I 逐条打一遍:首页、第 2 页、分类首页、分类第 2 页、文章页、页面。六个地址全绿,规则才算真的生效。