在 apache 中,使用 rewritecond %{request_filename} !-f 可以判断请求的文件在磁盘上不存在。结合 rewriterule 将请求自动映射到 index.php,通常用于实现前端路由或单入口模式。具体做法是:先检查请求路径是否对应一个真实存在的文件(如图片、css),如果不存在,则重写 url 指向 index.php。

如何配置 RewriteCond 排除真实文件并转发给 index.php?
要排除真实文件并将其他请求转发给 index.php,需要在 .htaccess 文件中启用 mod_rewrite,并使用 RewriteCond 检查 %{REQUEST_FILENAME} 是否不是一个普通文件(!-f)。同时,通常还需要检查它是否不是一个目录(!-d),以避免静态资源被错误拦截。当条件满足时,使用 RewriteRule 将所有匹配的请求重写到 index.php。

<IfModule mod_rewrite.c>
RewriteEngine On
# 如果请求的文件不存在
RewriteCond %{REQUEST_FILENAME} !-f
# 如果请求的目录不存在
RewriteCond %{REQUEST_FILENAME} !-d
# 将所有请求重写到 index.php
RewriteRule ^ index.php [L]
上述配置中,!-f 表示“不是文件”,!-d 表示“不是目录”。只有当两者都不满足时,请求才会被重写到 index.php。[L] 标志表示这是最后一条规则,停止处理后续规则。这样,像 /style.css 这样的真实文件会被直接访问,而 /user/profile 这样的动态路由则会交给 index.php 处理。
立即学习“PHP免费学习笔记(深入)”;
为什么需要同时检查 !-f 和 !-d?
仅使用 !-f 是不够的,因为如果请求的是一个真实存在的目录(例如 /images/),Apache 默认会尝试列出目录内容或返回 403 错误,而不是将其视为需要由 index.php 处理的动态路由。如果不加 !-d 检查,某些框架的路由可能与实际目录冲突,导致静态资源无法正确加载或目录访问异常。因此,同时排除文件和目录是确保静态资源和动态路由共存的最佳实践。

<IfModule mod_rewrite.c>
RewriteEngine On
# 检查是否为真实文件或目录
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# 重写到 index.php
RewriteRule ^ index.php [QSA,L]
在上述代码中,添加了 [QSA] 标志(Query String Append),以确保原始查询字符串(如 ?id=123)在重写后仍然保留。这对于后端处理参数非常重要。如果没有 QSA,查询字符串可能会被丢弃。通过同时检查 !-f 和 !-d,并附加 QSA,可以确保所有非静态资源的请求都能正确传递给 index.php,同时保留必要的查询参数。
当请求路径包含多个斜杠时,RewriteRule 如何匹配?
当请求路径包含多个斜杠(如 /api/v1/users)时,RewriteRule ^ index.php 中的 ^ 正则表达式会匹配整个路径。Apache 会将整个请求 URI(不包括查询字符串)作为输入传递给 index.php。在 index.php 中,可以通过 $_SERVER['REQUEST_URI'] 获取完整路径,并进行进一步的路由解析。这种机制允许框架根据路径结构动态决定如何处理请求。



















