6

我正在尝试更详细地了解以下 htaccess 规则:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
  RewriteRule (.+) index.php?p=$1 [QSA,L]
</IfModule>

具体来说,我试图了解 REQUEST_FILENAME 是如何工作的。我发现有几个资源可以讨论这个问题,从 mod_rewrite 文档到 Stack Overflow 上的答案。但似乎没有人能准确地解决我正在寻找的问题,我该如何仔细查看 REQUEST_FILENAME 变量以查看它的值?

通常,当我想查看 .htaccess 中引用的变量时,我将使用 print_r 查看 $_SERVER 全局变量,以查看这些值是什么服务器:

echo "<pre>";
print_r($_SERVER);
echo "</pre>";
die('fin');

这可以帮助我查看上面的 $_SERVER['REQUEST_URI'] 等值。但似乎 REQUEST_FILENAME 在我当前环境中的任何 PHP $GLOBALS 中都不可用。我确实看到了 SCRIPT_FILENAME 的值,并且有几个消息来源说这两个值是相等的,但不清楚它们是否是替代值,或者如果第一个不存在,则 REQUEST_FILENAME 是否回退到 SCRIPT_FILENAME。

通过稍微更新 htaccess 规则以输出 URL 中的值,我已经能够输出 REQUEST_FILENAME 值,将最后一行更改为:

RewriteRule (.+) index.php?p=%{REQUEST_FILENAME} [R=302,QSA,L]

但是为什么这个值在 PHP 的任何地方都不可用呢?有什么我忽略的东西可以帮助我了解这个变量的存储位置以及如何通过 PHP 查看它的值?

4

1 回答 1

5

RewriteCond

REQUEST_FILENAME
与请求匹配的文件或脚本的完整本地文件系统路径,如果在引用 REQUEST_FILENAME 时服务器已经确定了这一点。否则,例如在虚拟主机上下文中使用时,与 REQUEST_URI 的值相同。根据 AcceptPathInfo 的值,服务器可能只使用了 REQUEST_URI 的一些前导组件来将请求映射到文件。

并从$_SERVER

'SCRIPT_FILENAME'
当前执行脚本的绝对路径名。

REQUEST_URI如果实际对应于现有文件,这将是相同的(脚本的完整路径) 。

如果没有,REQUEST_FILENAME将只是REQUEST_URI并且SCRIPT_FILENAME将是正在执行的 PHP 脚本的名称。$_SERVER['REQUEST_URI']将是REQUEST_FILENAME(又名REQUEST_URI)。

在您的情况下,SCRIPT_FILENAME将始终是/path/to/index.php并且REQUEST_FILENAME/REQUEST_URI将可以通过$_SERVER['REQUEST_URI'].

更新

REQUEST_URI永远不会是文件名,因为它缺少文档根前缀。当你使用

RewriteCond %{REQUEST_URI} !-f

即使请求的 URL 与现有文件匹配,条件也将始终为真。以下RewriteRule将始终执行,尽管它应该调用另一个 PHP 脚本或提供 HTML、CSS 或图像文件。

更新

要真正回答这个问题。

但是为什么这个值在 PHP 的任何地方都不可用呢?

REQUEST_FILENAME在 PHP 中不可用,因为它不在环境或请求的标头中。

您在 PHP 中可以看到的只是一些环境变量或标头中的内容,或者 PHP 可以自行推断的内容。由于 PHP 不会尝试或无法在请求 URI 和某个文件名之间建立连接,因此您无法在任何地方访问它。REQUEST_FILENAME毕竟,它可能在文件系统中的任何地方。

但是,您可以自己将其放入环境中

RewriteRule (.+) index.php?p=$1 [QSA,L,E=REQUEST_FILENAME:%{REQUEST_FILENAME}]

并在 PHP 中以$_SERVER['REDIRECT_REQUEST_FILENAME'].

于 2013-04-10T20:45:34.320 回答