特定文件的mod_rewrite异常

Ste*_*ess 9 php apache .htaccess

我的页面没有重定向,因为我的.htaccess文件设置为:

RewriteEngine on  
RewriteCond $1 !^(index\.php|resources|robots\.txt)  
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteCond %{REQUEST_FILENAME} !-d  
RewriteRule ^(.*)$ index.php/$1 [L,QSA]   
Run Code Online (Sandbox Code Playgroud)

我使用这个设置为我的MVC框架,所以我得到网址, /controller/method/argument但是当我重定向到/forum/login.php它切换到/ forum /.

如何将此作为例外添加,以便我能够重定向到 /forum/login.php

我发现我的/ forum /目录中的另一个.htaccess也可能导致问题?

# BEGIN PunBB

<IfModule mod_rewrite.c>
    # MultiViews interfers with proper rewriting
    Options -MultiViews

    RewriteEngine On

    # Uncomment and properly set the RewriteBase if the rewrite rules are not working properly
    #RewriteBase /

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . rewrite.php [L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

Sve*_*ven 23

首先,我会告诉你如何阅读你的RewriteRule:

您从第一个(或下一个)RewriteRule条目开始:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

第一个参数是可以匹配您请求的URL的正则表达式.^(.*)$匹配所有内容,并将此"所有内容"存储在一个可以在以后使用的变量中.

只有当前有RewriteCond条目时,才会对它们进行评估:

RewriteCond $1 !^(index\.php|resources|robots\.txt)

$1是对RewriteRule的第一个括号内匹配的内容的引用.这相对于第二个参数,这是一个正则表达式,说明几个明确的名称和!否定的表达,如该规则允许只有在正则表达式不匹配重写规则的执行.如果此条件返回true,则将查看下一个条件.

RewriteCond %{REQUEST_FILENAME} !-f

如果请求的文件名不是硬盘上的真实文件,则此条件为真.

RewriteCond %{REQUEST_FILENAME} !-d

如果请求的文件名不是真实目录,则此条件为真.

只有当所有这些条件都成立时(它们与AND链接在一起),我们才会回到重写规则:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

该重写步骤的结果被定义为第二和第三参数.$1再次与匹配的内容一起使用,并且参数定义此规则(如果最初匹配)将是最后一个规则(L),并且重写目标中定义的任何查询字符串将附加到任何查询字符串中原始网址(QSA).

批判:

MVC框架的通常重写尝试尽可能高效.您的重写条件都必须进行评估才能成功重写.只有当任何RewriteCond返回false时,才会停止.每个被重写的请求都需要进行大量的cpu密集测试.首先是RewriteRule正则表达式,然后是第一个RewriteCond中的正则表达式,然后对文件系统进行两次硬盘测试,以确定是否存在文件.

另一方面,第一个RewriteCond似乎是不必要的.它测试某些名称,如果找到,则中止重写."index.php"应该被第二个RewriteCond检测到,因为它是一个现有文件(如果不是,那么重写将如何工作).任何以"资源"开头的东西也会匹配,但可能不应该出于同样的原因:第二个RewriteCond会找到现有资源.最后是"robots.txt"文件.如果你想在机器人获取你的网站时避免使用404,那么拥有一个可能是一个很好的主意.

由于您没有更改查询字符串中的任何内容,因此不需要[QSA]指令.

改进:

RewriteEngine on  
RewriteCond %{REQUEST_FILENAME} -f [OR] 
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]  
RewriteRule ^.*$ index.php [L]
Run Code Online (Sandbox Code Playgroud)

第一个RewriteRule将匹配整个请求的路径.两个RewriteCond与[OR]连接,因此返回true的第一个RewriteCond将取消进一步的评估.第一个RewriteCond测试所请求的文件是否存在.如果存在,则返回true,处理返回到第一个RewriteRule.目标表达式为" - ",表示"不重写".[L]停止进一步处理重写规则.所以最后,对于现有文件,我们只有一个正则表达式和一个文件系统测试,然后,这个现有文件将被发送到浏览器.

如果没有找到文件,第一个RewriteRule和RewriteCond将不会触发,因此[L]不会停止该过程.所以第二个RewriteRule被执行了.这个是无条件的,正则表达式与之前相同,匹配所有内容,并将其重写为"index.php".

如果存在任何文件,则此重写不会调用index.php,包括/forum/login.php.

RewriteRule ^.*$ index.php/$0 [L]如果您想要继续解析$_SERVER['PATH_INFO']而不是,则可以将第二个更改为$_SERVER['REQUEST_URI'].

  • 这是如此令人难以置信的彻底,需要更多的信用比它给予. (3认同)