自定义DocumentRoot下将v1子目录所有请求重定向至v1/index.php
问题:v1路径下的请求无法正确重定向到index.php
文件结构
.htaccess index.php public/ ├─ v1/ │ ├─ .htaccess │ ├─ index.php ├─ index.php
当前配置与需求
- 服务器已将
DocumentRoot设置为public子目录,目的是从URL中移除public路径 - 需求:所有包含
v1的请求,若对应文件/目录不存在,需重定向到v1/index.php(或v1/)
现有.htaccess配置
根目录.htaccess
RewriteEngine On RewriteCond %{REQUEST_URI} !public/ RewriteRule (.*) /public/$1 [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([^\.]+)$ $1.php [NC,L]
public/v1/.htaccess
RewriteCond %{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_FILENAME} !-d [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ index.php [QSA,L]
问题现象
- 预期行为:访问不存在的页面
https://example.com/v1/test时,重定向到https://example.com/v1/ - 实际结果:返回404错误:
Not Found The requested URL was not found on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
问题分析与解决方案
核心问题
- 根目录.htaccess完全无效:因为
DocumentRoot已设为public,Apache只会读取public目录及其子目录的.htaccess文件,根目录的配置不会被执行,属于冗余配置。 - v1目录.htaccess逻辑错误:原规则中的
[OR]条件组合无意义(!-f OR -f永远为真,!-d OR -d也永远为真),相当于没有添加任何条件限制,导致规则未按预期触发。
修正步骤
- 删除根目录的.htaccess文件:该文件不会被服务器读取,留着只会增加混淆。
- 修改public/v1/.htaccess文件:根据需求选择对应规则:
需求1:内部转发(URL保持v1/test,实际访问v1/index.php)
RewriteEngine On # 当请求的不是真实文件或目录时,转发到index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [QSA,L]
需求2:外部重定向(URL跳转为v1/,地址栏显示https://example.com/v1/)
RewriteEngine On # 排除真实文件、目录,以及v1根路径本身,其余请求重定向到v1/ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !^/v1/$ RewriteRule ^(.*)$ /v1/ [R=301,L]
补充说明
- 若使用外部重定向,建议先使用
R=302测试,确认生效后再改为R=301(永久重定向),避免浏览器缓存错误规则。 - 确保服务器已启用
mod_rewrite模块,否则所有Rewrite规则都不会生效。
内容的提问来源于stack exchange,提问作者Acidon
相关产品推荐
相关产品推荐

