今天做了什么

今天给这个 PHP Blog 系统实现了完整的伪静态 URL 支持,顺便把 Nginx 的重写规则也配好了。整体改动分三层:PHP 应用层、后台管理界面、Nginx 配置层。


一、PHP 应用层改动

新增的核心函数(frontend_helpers.php)

这是工作量最大的部分,在 frontend_helpers.php 里新增了一批专门处理伪静态 URL 的函数:

路由解析链:

  • blog_post_permalink_enabled() — 读取后台开关,判断伪静态是否启用
  • blog_parse_post_permalink_pattern(string $pattern) — 解析样式模板(比如 {cid}.html 或 post/{slug}.html),验证占位符合法性,返回结构化的线段数组;遇到非法输入直接抛 RuntimeException
  • blog_post_permalink_pattern_definition() — 带静态缓存的模板解析入口,避免重复解析
  • blog_validate_post_permalink_pattern(string $pattern) — 对外暴露的验证函数,返回错误字符串或 null
  • blog_build_post_permalink_path(array $post) — 把文章数据填入模板,生成实际的 URL 路径片段(如 5.html)
  • blog_match_post_permalink_path(string $path) — 用正则把请求路径反向匹对模板,提取 cid 或 slug
  • blog_resolve_post_from_permalink_path(string $path) — 从路径直接查库拿文章
  • blog_post_comment_url(array $post) — 生成评论表单的 action URL,伪静态开启时返回 /{cid}.html/comment,关闭时返回旧格式
  • blog_resolve_comment_target_from_path(string $path) — 同时兼容旧路由 archives/{cid}/comment 和新伪静态路由 {pattern}/comment
  • blog_detect_request_route_path() — 读 $_SERVER[REQUEST_URI],在 Nginx rewrite 场景下从完整 URI 里解出 path 部分

修改的已有函数:

  • blog_post_permalink() — 现在会判断伪静态开关,开启时生成 /blog/1.html 格式,关闭时回退到旧 ?path= 格式
  • blog_comment_permalink() — 评论永久链接同步适配新 URL
  • blog_fetch_recent_comments() — 在 SELECT 里补上 t.slug 字段,评论链接生成需要用到
  • 评论表单 action — 从硬编码 archives/{cid}/comment 改成调用 blog_post_comment_url($post)

index.php 路由改动

三处变更:

  1. 在 getPath() 后加了一行:if ($path === '') { $path = blog_detect_request_route_path(); } — 支持 Nginx rewrite 进来的请求($_GET[path] 是空的,但 URI 里有路径)
  2. POST 评论处理从固定正则改成 blog_resolve_comment_target_from_path($path),新旧路由都能收到评论
  3. 在 archives/{cid} handler 之前插入了伪静态路由 handler,先用 blog_resolve_post_from_permalink_path($path) 尝试解析,匹配成功就渲染文章页

二、后台管理界面(admin.php)

在设置页面加了两个字段:

☑ 启用文章伪静态
文章伪静态样式: [ {cid}.html            ]
支持占位符 {cid} 和 {slug},建议带上 .html 等后缀

POST 保存时会调用 blog_validate_post_permalink_pattern() 做格式校验,不合法的样式会拦下来给错误提示,不会写入。

两个 option key:postPermalinkEnabled("0" / "1")和 postPermalinkPattern(字符串,默认 {cid}.html)。


三、Nginx 配置(Laragon 本地环境)

这是让 /blog/1.html 真正能直接访问的关键。

改的文件:E:/laragon/etc/nginx/sites-enabled/00-default.conf

加了两个 location 块,插在 location / 之前:

# Blog 伪静态重写
# /blog/1.html → /blog/index.php?path=1.html
location /blog/ {
    try_files $uri $uri/ @blog_rewrite;
}

location @blog_rewrite {
    rewrite ^/blog/(.+)$ /blog/index.php?path=$1 last;
}

逻辑很清晰:先找实体文件(CSS、图片不受影响),找不到就把路径转给 index.php?path=,PHP 再解析。改完用 nginx -t 验证语法,再 nginx -s reload 热重载,不需要重启服务。


四、回归测试(tests/post_permalink_regression.ps1)

新建了一个 PowerShell 回归测试脚本,覆盖以下场景:

  1. 启用 {cid}.html 模式 → 请求 index.php?path={cid}.html → 断言 200 + 文章标题 + 页面内链接使用新格式
  2. 向 /{cid}.html/comment 发 POST 评论 → 断言 302 跳转回文章页
  3. 切换到 post/{slug}.html 模式 → 请求对应路径 → 断言 200 + slug 格式链接出现在页面
  4. 关闭伪静态 → 请求 /{cid}.html → 断言返回 404(旧路由有效,新路由失效)

测试里用了自定义的 Invoke-RequestWithoutRedirect(基于 System.Net.HttpWebRequest,AllowAutoRedirect = $false),避免 PowerShell 的 Invoke-WebRequest 把 302 响应吞掉。

结果:4 项全部通过。


总结

| 层级 | 文件 | 改动类型 |
|------|------|----------|
| PHP 应用 | frontend_helpers.php | 新增 11 个函数,修改 4 个 |
| PHP 路由 | index.php | 3 处改动(fallback、comment handler、rewrite handler)|
| 后台管理 | admin.php | 设置页新增 2 个字段 + POST 校验 |
| 服务器 | nginx/sites-enabled/00-default.conf | 新增 2 个 location 块 |
| 测试 | tests/post_permalink_regression.ps1 | 新建,4 个测试用例 |

整个系统的设计原则是应用层与服务器层解耦:后台开关控制 URL 样式,Nginx 只负责把找不到的路径转发给 PHP,PHP 自己识别是不是伪静态路径。这样即便换了服务器(Apache、Caddy),只需改对应的 rewrite 规则,PHP 侧不用动。

标签: 暂无标签

暂无评论

添加新评论