如何避免在 url 上输入 .php?
How to avoid the need of typing .php on the url?
我在 MacOs Big Sur 上使用 Apache 和 PHP。我想要的是:不需要将 .php
放在我的文件末尾来加载它。
例如,不要在 URL 上键入:
127.0.0.1/public_html/home.php
我只想输入
127.0.0.1/public_html/home
为了实现这一点,我在 .htaccess
:
中使用了这段代码
RewriteEngine On
Options -Indexes
DirectoryIndex home.php index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ .php [L]
上面的代码在我的主机上工作,但由于某种原因,它在我的开发机器上不工作。相反,出现 404 错误。
包含代码的 .htaccess
文件位于 public_html
文件夹的根目录中。
我错过了什么?
通过在 .htaccess
文件的顶部键入一些“废话”并且 不会 得到一个错误(通常你会得到一个 500 内部服务器错误)它会服务器上似乎未启用 .htaccess
覆盖。因此,.htaccess
个文件被有效地禁用了——它们在 Apache 2.4 上是默认的。
要启用 .htaccess
覆盖(允许 .htaccess
覆盖服务器配置),您需要在服务器的适当 <Directory>
容器中设置 AllowOverride
指令配置(或 <VirtualHost>
容器)。 Apache 2.4 上的默认值为 AllowOverride None
.
根据发布的指令,您至少需要:
AllowOverride FileInfo Indexes Options
FileInfo
代表 mod_rewrite,Indexes
代表 DirectoryIndex
,Options
代表 Options
和相关指令。
虽然通常(也更容易)设置:
AllowOverride All
参考:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ .php [L]
这些指令并不完全正确。虽然它们对于您正在测试的 URLs 可能工作正常,但如果您只是将斜杠附加到 URLs(并且没有目录),它们将导致重写循环(500 错误响应)以那个名字),例如。 /home/
(或/home/<anything>
)。这是因为测试 .php
文件是否存在的 条件 不一定与要重写的 URL 路径相同。参见 my answer to the following question on ServerFault for a thorough explanation of this issue: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error
此外,无需先检查请求是否映射到目录,然后再检查请求 + .php
扩展名是否映射到文件。如果请求映射到一个文件,那么它不能同时是一个目录,所以如果第二个条件为真,第一个条件也必须为真,因此是多余的。
并且在 RewriteCond
TestString 中不需要反斜杠转义文字点 - 这是一个“普通”字符串,而不是正则表达式。
所以,这些指令应该这样写:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule (.+) .php [L]
(RewriteBase
应该 而不是 在这里使用。)
您可以通过排除已经包含看起来像文件扩展名的请求来进一步优化这一点(假设您需要重写的 URL 不包含 URL 结尾附近的点 -小路)。例如:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}.php [L]
(对于第 2 个版本,是否设置 RewriteBase
并不重要 - 它未被使用。)
DirectoryIndex home.php index.php
您给出了 /public_html/home
的示例 URL(附加了 .php
)。然而,这个 DirectoryIndex
指令允许 home.php
在简单地请求目录 /public_html/
时也被提供。它应该是一个或另一个,而不是两者。
我在 MacOs Big Sur 上使用 Apache 和 PHP。我想要的是:不需要将 .php
放在我的文件末尾来加载它。
例如,不要在 URL 上键入:
127.0.0.1/public_html/home.php
我只想输入
127.0.0.1/public_html/home
为了实现这一点,我在 .htaccess
:
RewriteEngine On
Options -Indexes
DirectoryIndex home.php index.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ .php [L]
上面的代码在我的主机上工作,但由于某种原因,它在我的开发机器上不工作。相反,出现 404 错误。
包含代码的 .htaccess
文件位于 public_html
文件夹的根目录中。
我错过了什么?
通过在 .htaccess
文件的顶部键入一些“废话”并且 不会 得到一个错误(通常你会得到一个 500 内部服务器错误)它会服务器上似乎未启用 .htaccess
覆盖。因此,.htaccess
个文件被有效地禁用了——它们在 Apache 2.4 上是默认的。
要启用 .htaccess
覆盖(允许 .htaccess
覆盖服务器配置),您需要在服务器的适当 <Directory>
容器中设置 AllowOverride
指令配置(或 <VirtualHost>
容器)。 Apache 2.4 上的默认值为 AllowOverride None
.
根据发布的指令,您至少需要:
AllowOverride FileInfo Indexes Options
FileInfo
代表 mod_rewrite,Indexes
代表 DirectoryIndex
,Options
代表 Options
和相关指令。
虽然通常(也更容易)设置:
AllowOverride All
参考:
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule ^(.+)$ .php [L]
这些指令并不完全正确。虽然它们对于您正在测试的 URLs 可能工作正常,但如果您只是将斜杠附加到 URLs(并且没有目录),它们将导致重写循环(500 错误响应)以那个名字),例如。 /home/
(或/home/<anything>
)。这是因为测试 .php
文件是否存在的 条件 不一定与要重写的 URL 路径相同。参见 my answer to the following question on ServerFault for a thorough explanation of this issue: https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error
此外,无需先检查请求是否映射到目录,然后再检查请求 + .php
扩展名是否映射到文件。如果请求映射到一个文件,那么它不能同时是一个目录,所以如果第二个条件为真,第一个条件也必须为真,因此是多余的。
并且在 RewriteCond
TestString 中不需要反斜杠转义文字点 - 这是一个“普通”字符串,而不是正则表达式。
所以,这些指令应该这样写:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule (.+) .php [L]
(RewriteBase
应该 而不是 在这里使用。)
您可以通过排除已经包含看起来像文件扩展名的请求来进一步优化这一点(假设您需要重写的 URL 不包含 URL 结尾附近的点 -小路)。例如:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.php -f
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}.php [L]
(对于第 2 个版本,是否设置 RewriteBase
并不重要 - 它未被使用。)
DirectoryIndex home.php index.php
您给出了 /public_html/home
的示例 URL(附加了 .php
)。然而,这个 DirectoryIndex
指令允许 home.php
在简单地请求目录 /public_html/
时也被提供。它应该是一个或另一个,而不是两者。