
本文详解如何配置 apache 的 .htaccess 文件,使 css、js、图片等静态资源请求(如 `/css/main.css`)自动重写为 `public/css/main.css`,同时避免重定向循环,确保 mvc 路由与静态文件服务互不干扰。
在基于 MVC 架构的 PHP 应用中,将 Web 入口统一收敛至 public/index.php 是提升安全性和目录结构清晰度的重要实践。但随之而来的问题是:前端 HTML 中引用的相对路径(如 )会默认指向项目根目录下的 css/,而非实际存放于 public/css/ 的资源——这会导致 404 错误,除非手动在所有路径前添加 public/ 前缀,既繁琐又违背“开发友好”原则。
理想的解决方案是:通过 .htaccess 实现智能重写——对已知静态资源后缀(.css, .js, .png, .jpg, .woff2 等)的请求,自动前置 public/ 路径;对其他请求,则交由 public/index.php 统一处理(MVC 路由);同时必须规避重写循环(Rewrite Loop),这是多数失败配置的根本原因。
以下是经过生产验证的完整 .htaccess 配置(适配子目录部署场景,如 /BU/cs-602/developer-story/):
RewriteEngine On # 指定重写基准路径(仅本地开发或子目录部署时必需) RewriteBase /BU/cs-602/developer-story/ # 场景1:访问根路径或任何 index.* 页面 → 直接路由到 public/index.php,终止重写 RewriteRule ^(\/|.*index\..*)$ public/index.php [L,QSA] # 场景2:URL 已含 "public/" → 直接放行,避免重复添加 public/ 导致循环 RewriteRule ^(.*public\/.*)$ $1 [L,QSA] # 场景3:匹配非 PHP/HTML 的静态资源请求(如 .css, .js, .png 等) # 注意:此处使用 RewriteCond + RewriteRule 组合,比 RedirectMatch 更可控、更安全 RewriteCond %{REQUEST_URI} \.(?!php|htm|html)[a-zA-Z0-9]+$ [NC] RewriteRule ^(.*)$ public/$1 [L,QSA] # 场景4:剩余所有未命中上述规则的请求(即动态路由)→ 交由 MVC 入口处理 # 仅当请求路径不对应真实文件、目录或符号链接时才触发 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^([\w\d\s\-\_\/\%]*)$ public/index.php?p=$1 [L,QSA]
✅ 关键设计说明:
- [L] 标志至关重要:每个 RewriteRule 后紧跟 [L](Last),确保匹配后立即终止当前轮重写,防止后续规则误处理已修正的 URL;
- 优先级顺序不可颠倒:public/ 放行规则必须在静态资源重写之前,否则 public/css/main.css 会被再次重写为 public/public/css/main.css;
- 静态资源判断更健壮:使用 RewriteCond %{REQUEST_URI} \.(?!php|htm|html)[a-zA-Z0-9]+$ [NC] 精准匹配扩展名,支持大小写不敏感([NC]),并排除 .php/.html 等动态类型;
- 子目录兼容性:RewriteBase 确保所有相对路径重写均基于指定上下文(如 /BU/cs-602/developer-story/),无需硬编码完整路径;
- 调试建议:启用 Apache 的 RewriteLog(旧版)或 LogLevel alert rewrite:trace3(新版)可查看重写过程,快速定位循环或匹配失败问题。
? 最佳实践补充:
- 在 public/ 目录下放置 favicon.ico、robots.txt 等公共资源,它们将被直接服务,无需额外规则;
- 若需支持更多静态类型(如 .svg, .webp, .json),只需扩展 RewriteCond 中的否定断言,例如:\.(?!php|htm|html|json|svg|webp)[a-zA-Z0-9]+$;
- 生产环境建议禁用 .htaccess 解析(AllowOverride None),将规则移至虚拟主机配置中,以提升性能。
该方案彻底解耦了前端资源路径与后端部署结构,开发者可自由使用简洁相对路径,而服务器自动完成物理定位——真正实现“所见即所得”的开发体验。










