迅睿CMS URL 规则与伪静态:规则怎么写,改完老链接为什么全 404
迅睿CMS的路由内核始终基于查询参数,伪静态只是入口层把漂亮路径翻译回这串参数。这篇先讲清要翻译什么、URL 规则在后台哪里配,再给出 Nginx 与 Apache 的完整重写规则,最后解释改完规则后老链接为什么全部 404——链接生成与解析是两套逻辑——以及三种兼容处理方案和常见 404、500 的故障定位表。
迅睿CMS里「URL 规则」和「伪静态」是两个不同的东西:前者决定链接怎么生成,后者负责把漂亮路径翻译回查询参数。分开理解,改完路径老文章全 404 这类问题才不神秘。
一、URL 规则在哪配
后台「系统 → URL 规则」里,每个模块可以单独配。默认给的是几条常见形态:
列表页:/{dirname}/{page}.html
详情页:/{dirname}/{id}.html
栏目页:/{dirname}/list_{catid}.html
{dirname} 是模块目录名,{id} 是内容 ID,{catid} 是栏目 ID。这些是变量占位符,规则里能用的变量由系统预先定义,不能自己造。
二、伪静态只是在入口层翻译参数
迅睿的路由内核始终基于查询参数(index.php?s=news&c=show&id=5),伪静态干的事是把:
/news/show/5.html
重写成:
/index.php?s=news&c=show&id=5
注意 c=show 这一段——很多手写规则只翻译了 s 和 id,把 c 丢了,结果首页能进、详情页 404。控制器参数不能省。
三、Nginx 规则
location / {
if (!-e $request_filename) {
rewrite ^/([a-zA-Z0-9_]+)/show/([0-9]+)\.html$ /index.php?s=$1&c=show&id=$2 last;
rewrite ^/([a-zA-Z0-9_]+)/list/([0-9]+)\.html$ /index.php?s=$1&c=list&catid=$2 last;
rewrite ^/([a-zA-Z0-9_]+)/list/([0-9]+)_([0-9]+)\.html$ /index.php?s=$1&c=list&catid=$2&page=$3 last;
rewrite ^/([a-zA-Z0-9_]+)/?$ /index.php?s=$1 last;
}
}
四条分别对应详情、列表首页、列表分页、模块首页。if (!-e $request_filename) 这句不能删——它让真实存在的静态文件(static/ 下的 css、js、图片)直接返回,不进 PHP。删了以后每次请求图片都要过一次 PHP,站点会明显变慢。
四、Apache 规则
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_]+)/show/([0-9]+)\.html$ index.php?s=$1&c=show&id=$2 [L]
RewriteRule ^([a-zA-Z0-9_]+)/list/([0-9]+)\.html$ index.php?s=$1&c=list&catid=$2 [L]
[L] 是「匹配即停」,和 Nginx 的 last 同义。漏了它,规则会叠加执行,可能出现参数被后一条覆盖的情况。
五、404 还是 500:故障定位表
| 现象 | 原因 |
|---|---|
| 全站 404 | 重写模块没开(Apache 的 mod_rewrite)或 AllowOverride 为 None |
| 首页正常,详情 404 | 规则漏了 c=show,或正则没匹配到扩展名 |
| 详情正常,列表 404 | 缺 list 那条规则 |
| 分页全跳第一页 | 缺 page 参数那条,或正则把 _2 当成了 catid 的一部分 |
| 500 | 重写目标写错路径,导致 PHP 循环重写自身,或 last 写成 break 后参数没传进 PHP |
| 打开伪静态后后台进不去 | 规则把 /admin.php 也重写了,需加 RewriteCond %{REQUEST_URI} !^/admin |
500 那条值得单独说:Nginx 的 last 和 break 区别在这类场景里很致命。last 会重新走一遍 location 匹配,break 直接在当前 location 停下。重写到 /index.php 必须用 last,用 break 时 query 参数不会重新解析,表现为页面白屏或参数为空。
六、改完 URL 规则,老链接为什么全 404
流程是这样的:
- 模板里
{\$t.url}按当前规则实时生成链接。 - 访问时,程序按当前规则反向解析出参数。
- 规则一改,两边同时变,新链接没问题。
- 但搜索引擎和外部引用的老链接是按老规则写的,新规则解析不出来,就 404。
所以 404 的不是文章没了,是地址对不上号。文章数据完好,只是入口换了。
七、三种处理方式
方式一:别改(推荐)
上线前就把规则定好。已经稳定收录的站,改 URL 的收益通常小于流量损失。
方式二:保留老规则做 301 兼容
# Nginx:老规则 /news/123.html -> 新规则 /news/show-123.html
rewrite ^/news/(\d+)\.html$ /news/show-$1.html permanent;
# Apache
RewriteRule ^news/(\d+)\.html$ /news/show-$1.html [R=301,L]
注意是 301 永久重定向,不是 302。301 才能把权重传过去。
方式三:拿别名当路径
详情页:/{dirname}/{alias}.html
好处是可读、对 SEO 友好;代价是别名必须唯一。别名重复时,后发布的那篇会解析失败——这是最容易忽略的坑,发布前要校验别名唯一性。老链接一样要 301。
八、栏目层级路径
栏目有父子关系时,路径要带层级,比如 /news/tech/123.html。配置里用栏目路径变量而非 ID:
详情页:/{catdir}/{id}.html
{catdir} 取的是栏目目录名,含父级时会是 news/tech 这种形式。父栏目改名会导致子栏目路径全变,所以栏目目录名发布后就别动了。
九、canonical 与重复内容
开启伪静态后,/news/show/5.html 和 /index.php?s=news&c=show&id=5 会同时可访问;/news/ 和 /news/index.html 也常常都能打开。同一份内容两个地址,搜索引擎会当成两个页面。
处理办法是统一到其中一个,另一个 301 过去,并在页面里写死 canonical 指向伪静态地址。
if ($args ~ "^s=") {
return 301 /;
}
但直接 301 到首页会丢掉原链接权重,更稳妥的是模板 head 里输出 canonical。迅睿这块不自动处理,得自己配。
十、改规则前必做的两件事
- 备份现有配置:
cp nginx.conf nginx.conf.bak,改错能立刻回滚,不用翻日志猜。 - 先关再开:后台关掉伪静态 → 确认
s=形式能访问 → 配好规则 → 再后台开启。开着伪静态改规则,你连自己站点是死是活都判断不了。
十一、验证清单
- 随便挑三篇,新链接能打开
- 列表页、栏目页、详情页三类都通
- 老链接是 301 到新链接,不是 404
- 页面
<link rel="canonical">指向新地址且唯一 - sitemap 重新生成,里面是新地址不是旧地址
- 分页第二页正常(
{page}为 1 时最容易漏)
六条全过,才算改完。
下一篇写缓存:后台改了内容前台不更新、缓存清了还是旧页面,问题到底出在哪一层。