如何配置Apache使index.php目录索引支持AcceptPathInfo路径信息行为?
问题原因与解决方案
核心问题
你的规则失效是因为%{REQUEST_FILENAME}的取值逻辑差异:
- 当请求
/aaa/bbb/ccc且/aaa.php存在时,/aaa既不是文件也不是目录,Apache会将%{REQUEST_FILENAME}设为DOCUMENT_ROOT/aaa,此时%{REQUEST_FILENAME}.php指向存在的/aaa.php,规则触发。 - 但当
/aaa是存在的目录时,请求/aaa/bbb/ccc会让%{REQUEST_FILENAME}指向不存在的DOCUMENT_ROOT/aaa/bbb/ccc,此时%{REQUEST_FILENAME}/index.php检查的是/aaa/bbb/ccc/index.php(不存在),规则自然不生效。
解决方案
要实现类似.php文件的重写效果,需要直接从请求URI中提取存在的目录前缀,而非依赖%{REQUEST_FILENAME}。以下是两种可行方案:
方案1:固定层级规则(适合已知目录深度场景)
# 处理二级路径请求:/aaa/bbb/ccc → /aaa/index.php/bbb/ccc RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} ^(/[^/]+)(/.*)$ RewriteCond %{DOCUMENT_ROOT}%1/index.php -f RewriteRule ^ %1/index.php%2 [END] # 处理三级路径请求:/aaa/bbb/ccc/ddd → /aaa/bbb/index.php/ccc/ddd RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} ^(/[^/]+/[^/]+)(/.*)$ RewriteCond %{DOCUMENT_ROOT}%1/index.php -f RewriteRule ^ %1/index.php%2 [END] # 处理根目录请求:/bbb/ccc → /index.php/bbb/ccc RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} ^/(.+)$ RewriteCond %{DOCUMENT_ROOT}/index.php -f RewriteRule ^ /index.php/%1 [END]
方案2:自动循环规则(支持任意目录深度)
该规则会自动从请求路径末尾逐步缩短,直到找到存在index.php的目录:
# 保存原始请求路径到环境变量 RewriteCond %{ENV:ORIG_URI} ^$ RewriteRule ^(.*)$ - [E=ORIG_URI:$1] # 循环缩短路径,直到找到包含index.php的目录 RewriteCond %{REQUEST_FILENAME}/index.php !-f RewriteRule ^(.+)/[^/]+$ $1 [N] # 执行重写,拼接剩余路径 RewriteCond %{REQUEST_FILENAME}/index.php -f RewriteRule ^(.*)$ $1/index.php/%{ENV:ORIG_URI} [END] # 修正路径中的重复前缀(如/aaa/index.php/aaa/bbb/ccc → /aaa/index.php/bbb/ccc) RewriteCond %{REQUEST_URI} ^(/[^/]+)/index.php/\1(/.*)$ RewriteRule ^ %1/index.php%2 [END]
效果验证
当/aaa/index.php存在时,请求https://example.com/aaa/bbb/ccc会被重写为https://example.com/aaa/index.php/bbb/ccc,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Matthijs Steen
相关产品推荐
相关产品推荐

