首页 > 解决方案 > 如何为 Apache 编写 .htaccess 文件以附加 PHP(如果未提供)并使用编写良好的 404 页面

问题描述

在 Apache 中,我有一个有效的 .htaccess 文件,它将 .php 扩展名附加到请求的网站页面,例如: https://{{domain}}/sales -> 提供来自 https://{{ 的内容domain}}/sales.php 而对访问者来说,它看起来像 https://{{domain}}/sales

它工作完美。

但是,我无法解决如何也使用服务器上花哨的 404.php 页面。

这是我当前的 .htaccess 文件内容:

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

证据:如果我关闭我的 .htaccess 文件(重命名它),根据我的 httpd.conf 设置,404 页面运行良好。因此,我几乎可以肯定,当找不到 sales.php 页面时,正是这个不成熟的 .htaccess 文件阻止了我提供精美的 404 页面。

httpd.conf 中的确切行是什么:

DocumentRoot "/var/www/html/"
ErrorDocument 404 "/404.php"

此外,我已经尝试了每一个:(并在之后重新加载了 httpd)

ErrorDocument 404 "/var/www/html/{{virtualHostDir}}/404.php"
ErrorDocument 404 "/404.php"
ErrorDocument 404 "404.php"

我什至尝试将 ErrorDocument 直接添加到 virtualHost 设置中,但无济于事。


当你得到一个 404 并且 .htaccess 文件就位时,实际上会发生什么?

我得到一个没有 html 的页面,它只是说“找不到文件”。

标签: phpapache.htaccesserrordocument

解决方案


DocumentRoot "/var/www/html/"
ErrorDocument 404 "/404.php"

这看起来是正确的。如果 404 错误文档位于,/var/www/html/404.php那么没有明显的原因(根据给定的信息)为什么它不能按预期工作。它似乎不是.htaccess文件的内容 - 尽管您可以尝试另一种方法(见下文)。

提供给ErrorDocument指令的路径应该是相对于文档根目录的 URL 路径 - 以斜杠开头。(为了触发对相应错误文档的内部子请求。)

我什至尝试将 ErrorDocument 直接添加到 virtualHost 设置中

但是,如果您使用的是 VirtualHost 容器,那么这些设置实际上应该在各自的 vHost(s) 中。vHost 中的任何内容都将覆盖主服务器配置。

显然,如果您对服务器配置/虚拟主机进行任何更改,那么您将需要重新启动 Apache。

由于您.htaccess无论如何都在使用,您还可以设置ErrorDocumentin .htaccess- 这将反过来覆盖虚拟主机/服务器配置。

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

这没有什么特别的问题......您正在匹配一个不包含点的请求的 URL 路径,并且如果它尚未映射到文件或目录,则您正在附加.php扩展名。

关于此的一些注释:

  • .php无论“带有.php扩展名”的文件是否实际存在,您都可以附加扩展名。这不一定是错误的,只是 404 然后被触发/does-not-exist.php而不是/does-not-exist. 您可以改为检查目标文件是否存在。这将避免必须检查请求是否尚未映射到文件或目录。

  • 检查请求未映射到文件的第一个条件可能是不必要的,除非您有没有文件扩展名的文件(我认为这不太可能)。

  • [^\.]- 无需反斜杠转义正则表达式字符类中的文字点。(虽然这样做没有害处,除了可读性IMO。)

  • $1\.phpRewriteRule -替换中的文字点无需反斜杠转义。这个参数是一个“普通”字符串(不是正则表达式),点在这里没有特殊含义。(尽管如此,这样做并没有什么坏处,除了可读性。)

  • 此处不需要该NC标志,因为您要匹配正则表达式中的点以外的所有内容,无论如何它自然包括大写和小写字母。RewriteRule

  • 如果这就是您使用 mod_rewrite 的全部内容,那么您可以改用 MultiViews 来处理您的无扩展 URL。这就是 MultiViews(mod_negotiation 的一部分)所做的。给定一个请求/path/to/foo,如果/path/to/foo.php存在,mod_negotiation 将提供该文件。您需要删除现有的 mod_rewrite 指令(因为它们实际上会发生冲突并被忽略),然后在.htaccess文件顶部启用 MultiViews:

    Options +MultiViews
    

或者,考虑到我上面提出的观点,尝试以下操作:

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]

注意:我假设您的.htaccess文件位于文档根目录中,即。/var/www/html/.htaccess?


推荐阅读