嵌套 URL 的 Apache2 .htaccess 重写规则不起作用

Apache2 .htaccess rewrite rule for nested URLs doesn't work

我有一个简单的 php 应用程序,其导航基于 domain/foo/bar 嵌套的 urls。

例如,我的主页 index.phpabout 导航 link 应该导航到 domain/en/about,其中 enabout 必须转移到 url 参数,如 index.php?url=....

但是当我点击 about 时,我 domain/en/about 并且 404 not found 相反。

我已将 apache2 虚拟域配置配置为:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    <Directory /var/www/html/domain>
         Options -Indexes +FollowSymLinks -MultiViews
         AllowOverride All
         Require all granted
     </Directory>
    DocumentRoot /var/www/domain/   
    ServerName domain.local
    ServerAlias www.domain.local
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

.htaccess文件为:

order deny,allow
RewriteEngine On
RewriteBase /
RewriteRule .* index.php?url=[=11=] [QSA,L]

mod_rewrite for apache2 已经启用。

不知道我错过了什么。

感谢任何帮助! 提前致谢!

您需要在要捕获的内容周围加上括号。 Back-references 索引以“1”开头:

RewriteRule (.*) index.php?url= [L,QSA]
<Directory /var/www/html/domain>
:
DocumentRoot /var/www/domain/

您的 <Directory> 部分和 DocumentRoot 指令指向不同的位置,因此无论您将 .htaccess 文件放在哪里,它都不会按预期工作。

然而...

RewriteRule .* index.php?url=[=11=] [QSA,L]

这条规则并不严格正确,因为它最终会在重写引擎第二次通过时重写自己。如果不是 QSA 标志,原始的 url 参数值(包含最初请求的 URL-path)将会丢失。上面的代码最终将 /en/about 的请求重写为 index.php?url=index.php&url=en/about。幸运的是,您的 PHP 脚本仍将 $_GET['url'] 读作 en/about。但是您可以检查 $_SERVER['QUERY_STRING'].

中的完整(错误)查询字符串

(而且,如果您只是在 替换 字符串前加上斜杠,即 URL-path,您将得到无穷无尽的 rewrite-loop(500 内部服务器错误)。但这也可能是由于稍后添加其他规则造成的。)

您应该防止对 index.php 本身的请求被重写,您可以通过添加额外的规则来做到这一点。例如:

RewriteRule ^index\.php$ - [L]
RewriteRule .* index.php?url=[=12=] [QSA,L]

但是,这仍然会重写您的静态资产(假设您正在链接到内部图像、CSS 和 JS 文件?)。因此,您通常需要使用额外的 条件 来防止这种情况,如果请求已经映射到静态文件,则阻止处理规则。

例如:

RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php?url=[=13=] [QSA,L]

CondPattern -f 检查 TestString 是否映射到文件。 ! 前缀否定了这一点。因此,只有当请求 not 映射到文件时,条件才会成功。