
本文讲解如何通过 apache 的 .htaccess 文件正确配置 url 重写规则,使访问如 /items/general 时由 items/index.php 统一处理,而非根目录 index.php 或返回 404。核心在于 rewriterule 的路径匹配逻辑与作用范围。
本文讲解如何通过 apache 的 .htaccess 文件正确配置 url 重写规则,使访问如 /items/general 时由 items/index.php 统一处理,而非根目录 index.php 或返回 404。核心在于 rewriterule 的路径匹配逻辑与作用范围。
在 PHP Web 开发中,常需实现“前端控制器模式”(Front Controller Pattern)——即让子目录下的 index.php 充当该目录所有请求的统一入口。例如,项目结构如下:
/htdocs/
├── index.php # 根目录入口(主站)
└── items/
└── index.php # 子目录专用入口(用于 items/* 路由)
目标是:当用户访问 https://example.com/items/general、/items/list?sort=desc 或 /items/123/edit 时,均由 /items/index.php 接收并解析请求路径,而不是触发 404 或误入根目录 index.php。
✅ 正确配置方式(推荐)
在 /items/.htaccess 文件中写入以下内容(注意文件名是 .htaccess,不是 .htacces):
RewriteEngine On
RewriteBase /items/
# 将所有进入 /items/ 下的请求(无论路径)转发给 index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]
? 关键说明:
- RewriteBase /items/:明确告诉 Apache 当前 .htaccess 所在上下文路径,避免重写路径计算错误;
- RewriteCond %{REQUEST_FILENAME} !-f 和 !-d:仅当请求路径不对应真实文件或目录时才重写(防止 CSS/JS/图片等静态资源被错误拦截);
- ^(.*)$:匹配任意非空路径(包括 general、list/123、api/json 等);
- [L,QSA]:L 表示终止后续规则;QSA(Query String Append)确保原始查询参数(如 ?page=2)自动透传到 index.php。
⚠️ 注意:根目录 .htaccess 不应干扰子目录规则。若根目录也有重写逻辑,请确保其 RewriteRule 不覆盖 /items/ 前缀(例如避免使用 ^.*$ 无条件捕获)。
? 示例:items/index.php 如何读取原始路径
在 /items/index.php 中,可通过 $_SERVER['REQUEST_URI'] 获取完整请求路径,并做路由分发:
<?php // items/index.php
$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$pathParts = array_filter(explode('/', $requestUri));
// 示例:/items/general → $pathParts = ['items', 'general']
if (isset($pathParts[1])) {
$action = $pathParts[1];
switch ($action) {
case 'general':
echo "<h1>General Section";
break;
case 'list':
echo "<h1>Item List</h1>";
break;
default:
http_response_code(404);
echo "<h1>Not Found</h1>";
}
} else {
echo "<h1>Items Home</h1>";
}
❌ 原方案为何失败?
你最初尝试的规则:
RewriteRule ^/?$ items/index.php [L]
仅匹配空路径(即 /items/ 或 /items),而 /items/general 完全不满足 ^/?$,因此 Apache 直接查找物理路径 items/general,找不到就返回 404。
而答案中建议的 RewriteRule items/ items/index.php [L] 虽能触发,但存在严重缺陷:它会在任何包含 items/ 的 URL 中触发(如 /blog/items/post),且未启用 QSA,也未排除静态资源,不推荐在生产环境使用。
✅ 最佳实践总结
- ✅ 将 .htaccess 放在子目录(如 /items/.htaccess),而非根目录;
- ✅ 始终使用 RewriteBase 明确上下文;
- ✅ 添加 !-f / !-d 条件保护静态资源;
- ✅ 使用 QSA 保留查询参数;
- ✅ 在 index.php 中用 parse_url($_SERVER['REQUEST_URI']) 安全提取路径;
- ❌ 避免模糊正则(如 (\w+)/)或无条件重写,以防规则冲突或安全风险。
完成配置后,重启 Apache 或清除浏览器缓存,即可验证 /items/anything?param=value 均由 items/index.php 成功接管。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











