使用.htaccess去除.php扩展名

135

是的,我已经阅读了Apache手册并在这里搜索。出于某种原因,我无法让它起作用。最接近的我做到的是删除扩展名,但它指向根目录。我希望它只在包含.htaccess文件的目录中正常工作。

我需要在.htaccess文件中进行三件事。

  1. 我需要它去掉.php

a. 我有几个页面使用选项卡,并且URL看起来像page.php#tab - 这是可能的吗?

b. 我有一个页面,使用会话ID附加到URL以确保您来自正确的位置,www.domain.example/download-software.php?abcdefg

这是可能的吗?在执行此操作时,我是否需要从标头nav包含文件中的链接中删除.phpIE "<a href="support.php">support</a>"应该改为<a href="support">support</a>吗?

  1. 我想强制在每个URL之前添加www,因此它不是domain.example,而是www.domain.example/page
  2. 我想从页面中删除所有尾随斜杠。

我会继续寻找、尝试等。在子目录中会有任何问题吗?


我只是好奇,这有什么好处吗?这是为了让你的用户不知道他们正在访问你服务器上的哪个文件吗? - Kellen Stuart
双重折叠。这样他们就不知道我们正在提供哪些文件类型,而且在我看来它看起来更加整洁。 - Dirty Bird Design
另一个相关的问题:https://dev59.com/lGw15IYBdhLWcg3wkMjz。 - Edward
如果下面提供的解决方案都无效,请查看此帖子https://helponnet.com/2020/02/04/remove-html-and-php-extension-with-htaccess-rewriterule-url-rewriting-tips/并学习如何自行解决。 - Amit Verma
18个回答

149

Gumbo在Stack Overflow问题如何使用Apache mod_rewrite隐藏.html扩展名中的回答应该可以很好地运作。

对于1),将.html更改为.php

a)是的,那是可能的,只需将#tab添加到URL即可。

b)可以使用QSA(查询字符串附加),请参见下文。

这个方法也适用于子目录路径:

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule !.*\.php$ %{REQUEST_FILENAME}.php [QSA,L]

谢谢你的帮助,伙计。出于某种原因,我敢打赌是由于 PHP 文件中硬编码的会话附加 URL,我能够在没有上述操作的情况下访问它。我真的很感激你的帮助,这个 .htaccess 的东西对我来说很棘手。 - Dirty Bird Design
9
请移除 [L,QSA] 之间的空格,否则会导致 _500 内部服务器错误_。 - Rahil Wazir
1
这将使/index/bla/blaindex.php相同。 - elkebirmed
如果文件名已经以 .php 结尾,则不需要重写,否则只需添加 .php 后缀即可。 - mmiddleton

76

Apache mod_rewrite

你需要的是mod_rewrite

描述: 提供了一个基于规则的重写引擎,可以实时重写请求的URL。

一般来说,mod_rewrite通过匹配指定的正则表达式来处理请求的文档,然后在Apache进程内部(内部重写)或客户端浏览器中(外部重写)执行URL重写。这些重写可以简单地将example.com/foo内部转换为对example.com/foo/bar的请求。

Apache文档包含一个mod_rewrite指南,我认为其中涵盖了您想要做的一些事情。详细的mod_rewrite指南

强制使用www子域名

我希望它在每个URL之前都强制使用"www",所以不是domain.example而是www.domain.example/page

重写指南包含了这方面的说明,在规范主机名示例下。

删除尾随斜杠(第一部分)

我想要删除所有页面的尾随斜杠

我不确定为什么您要这样做,因为重写指南包括相反的示例,即始终包含尾随斜杠。文档建议删除尾随斜杠可能会导致问题:

尾随斜杠问题

描述:

每个网站管理员都能唱出关于URL引用目录时尾随斜杠的问题。如果缺少它们,服务器就会抛出一个错误,因为如果你说/~quux/foo而不是/~quux/foo/,那么服务器将搜索名为foo的文件。由于此文件是目录,它会抱怨。实际上,在大多数情况下,它会尝试自行修复,但有时需要您模拟此机制。例如,在您完成了许多复杂的URL重写到CGI脚本等之后。

也许您可以解释一下为什么您想始终删除尾随斜杠?

删除.php扩展名

我需要它删除.php

我能想到的最接近实现此目的的方法是将每个请求文档内部重写为 .php 扩展名,即 example.com/somepage 实际上被处理成了对 example.com/somepage.php 的请求。请注意,这样做需要确保每个somepage实际上存在于文件系统上作为 somepage.php。
通过正确组合正则表达式,这应该在一定程度上是可行的。但是,我可以预见到一些可能出现的问题,例如索引页面未能正确请求和无法正确匹配目录。
例如,这将正确地将 example.com/test 重写为对 example.com/test.php 的请求:
RewriteEngine  on
RewriteRule ^(.*)$ $1.php

但是,由于没有example.com/.php,将导致example.com无法加载。

我猜测,如果您删除所有尾随斜杠,则从对父目录中文件名的请求中选择对目录索引的请求将变得几乎不可能。您如何确定对目录"foobar"的请求:

example.com/foobar

从一个请求名为foobar的文件中(实际上是foobar.php文件)

example.com/foobar

如果您使用RewriteBase指令,可能是可行的。但如果您这样做,那么这个问题会变得更加复杂,因为您需要使用RewriteCond指令来进行文件系统级别的检查,以确定请求是否映射到目录或文件。
话虽如此,如果您放弃删除所有尾随斜杠的要求,而是强制添加尾随斜杠,“无 .php 扩展名”问题就会变得更加合理一些。
# Turn on the rewrite engine
RewriteEngine  on
# If the request doesn't end in .php (Case insensitive) continue processing rules
RewriteCond %{REQUEST_URI} !\.php$ [NC]
# If the request doesn't end in a slash continue processing the rules
RewriteCond %{REQUEST_URI} [^/]$
# Rewrite the request with a .php extension. L means this is the 'Last' rule
RewriteRule ^(.*)$ $1.php [L]

这还不完美--每个文件请求仍然在内部附加了.php。请求“hi.txt”将在您的错误日志中记录如下:

[Tue Oct 26 18:12:52 2010] [error] [client 71.61.190.56] script '/var/www/test.peopleareducks.com/rewrite/hi.txt.php' not found or unable to stat

但是还有另一种选择,可以像这样设置DefaultTypeDirectoryIndex指令:
DefaultType application/x-httpd-php
DirectoryIndex index.php index.html

2013-11-14更新 - 修正了上面代码片段中nicorellius的观察结果

现在可以成功请求hi.txt(以及其他任何文件),对于example.com/test的请求将返回处理过的test.php版本,index.php文件也将再次正常工作。

我必须为这个解决方案所给予的信誉致谢,因为我通过谷歌搜索php no extension apache找到了Michael J. Radwins Blog

删除末尾斜杠

一些搜索关于apache remove trailing slashes的结果带我来到了一些搜索引擎优化页面。显然,某些内容管理系统(本例中为Drupal)会使内容在URL中有或没有末尾斜杠可用,在SEO领域中这会导致您的网站遭受重复内容惩罚。来源

解决方案似乎非常简单,使用mod_rewrite,我们在请求资源以/结束的条件下进行重写,并通过发送301永久重定向 HTTP头来重写URL。

这是他的示例,假设您的域名为blamcast.net,并允许请求以www.作为前缀。

#get rid of trailing slashes
RewriteCond %{HTTP_HOST} ^(www.)?blamcast\.net$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]

现在我们有所进展了。让我们把它们放在一起,看看它是什么样子。

强制使用www.,不使用.php,以及不要使用尾随斜杠

这假设域名为foobar.example,并且它正在标准端口80上运行。

# Process all files as PHP by default
DefaultType application/x-httpd-php
# Fix sub-directory requests by allowing 'index' as a DirectoryIndex value
DirectoryIndex index index.html

# Force the domain to load with the www subdomain prefix
# If the request doesn't start with www...
RewriteCond %{HTTP_HOST}   !^www\.foobar\.com [NC]
# And the site name isn't empty
RewriteCond %{HTTP_HOST}   !^$
# Finally rewrite the request: end of rules, don't escape the output, and force a 301 redirect
RewriteRule ^/?(.*)         http://www.foobar.example/$1 [L,R,NE]

#get rid of trailing slashes
RewriteCond %{HTTP_HOST} ^(www.)?foobar\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]

'R'标志在RewriteRule指令部分中有描述。摘录:

redirect|R [=code](强制重定向)前缀替换为http://thishost[:thisport]/(使新URL成为URI),以强制进行外部重定向。如果未提供代码,则将返回HTTP响应302(暂时移动)。

最终说明

我无法成功地使斜杠删除工作。重定向最终导致我无限重定向循环。在仔细阅读原始解决方案后,我认为上面的示例适用于他们的Drupal安装方式。他特别提到:

在启用了干净的URL的普通Drupal网站上,这两个地址基本上是可以互换的

关于以斜杠结尾和不带斜杠的URL。此外,

Drupal使用一个名为.htaccess的文件告诉您的Web服务器如何处理URL。这是启用Drupal的干净URL魔术的同一文件。通过在.htaccess文件开头添加一个简单的重定向命令,您可以强制服务器自动删除任何尾随斜杠。


我喜欢看到深思熟虑、有组织的答案。干得好... 我注意到一件事:你是不是想说 DirectoryIndex index index.html?还是 DirectoryIndex index.php index.html - nicorellius
@nicorellius,我相信你是正确的。我已经根据你的观察更新了我的原始答案。 - Tim Bielawa
1
我必须说,这并不总是有效。请尝试下面的回答(来自1079877用户)。 - DonJoe
你是真正的MVP。 - ZainZaheer06
直到我添加了 Options Indexes FollowSymLinks,才使得一切正常运作。 - Íhor Mé
显示剩余3条评论

65

除了以上其他答案,

您还可以尝试此方法完全删除文件中的.php扩展名并避免无限循环

RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ $1.php [NC,L]

如果您想将此代码放置在子目录的htaccess文件中,请确保更改RewriteBase。该代码将适用于Root /.htaccess。

在Apache 2.4及更高版本中,您还可以使用END标志来防止无限循环错误。以下示例在Apache 2.4上与上述示例相同。

RewriteEngine on

RewriteRule ^(.+)\.php$ /$1 [R,L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*?)/?$ /$1.php [NC,END]

1
与其他的不同,这个也可以处理文件夹(例如example.com/1(php文件)和example.com/2/(文件夹)都可以工作),但是重定向会破坏表单。 - ethry
1
这应该被接受的答案。!!! - Shurvir Mori

26

以下代码对我来说正常运行:

RewriteEngine on 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME}\.php -f 
RewriteRule ^(.*)$ $1.php

这个可以工作,但是 example.com 会变成所有文件和目录的索引。(Apache 2.4) - earth2jason

15

在Debian 8中,根据这个,将/etc/apache2/apache2.conf中的AllowOverride参数从None更改为All后,仅需在.htaccess文件中包含以下内容:

Options +MultiViews
AddHandler php5-script php
AddType text/html php

这足以隐藏文件中的.php扩展名


1
希望这个更高一些。当MultiViews可以直接完成此操作时,为什么要费心进行URL重写的开销呢? - Phil
这很棒。有什么缺点吗? - reformed
@reformed 谢谢。我不得不在源代码中将链接从 <a href="somepage.php">link</a> 更改为 <a href="somepage">link</a> - Rodney Salcedo
1
MultiViews 实际上可以在所有内容上启用无扩展名的 URL。您的所有静态资源(图像、CSS、JS 等)也可以使用文件扩展名或不使用文件扩展名来访问。然而,最大的“缺点”之一是与 mod_rewrite 的意外冲突,因为 MultiViews(mod_negotiation)首先被处理并有效地重写 URL,然后将“重写”的 URL 交给 mod_rewrite。这可能会导致 mod_rewrite 指令与您预期的请求不匹配。@reformed - MrWhite
仍然适用于2022年。 - Matias Jimenez

15

我最终得到了以下有效的代码:

RewriteEngine on 
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]

14

9

试试这个
下面的代码一定会起作用

RewriteEngine on
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,L,R]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [NC,L]

8

我不确定为什么其他答案对我无效,但我找到了这段代码:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

这是我htaccess中的全部内容:example.com/page 显示为 example.com/page.php

5
要从PHP文件中去除.php扩展名,例如将yoursite.example/about.php改为yoursite.example/about,请按照以下步骤操作:在您的网站根目录下打开.htaccess文件(如果不存在,请创建一个新的),并添加以下代码。
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

为了将HTML文件的扩展名.html从例如yoursite.example/about.html改为yoursite.example/about,请按照以下步骤操作:打开您网站根目录下的.htaccess文件(如果不存在则创建一个新的),并添加以下代码。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.html [NC,L]

参考: 如何从URL中移除PHP扩展名


这会破坏文件夹。 - ethry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接