9

由于我的 .htaccess 文件设置为:

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

我将这个设置用于我的 MVC 框架,所以我得到类似的 url, /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>
4

2 回答 2

24

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

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

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

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

仅当存在前面的 RewriteCond 条目时,它们才会被评估:

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

$1是对 RewriteRule 的第一个括号内匹配的内容的引用。这与第二个参数进行比较,第二个参数是一个正则表达式,说明几个显式名称,并且!否定表达式,例如,此规则仅在正则表达式不匹配时才允许执行 RewriteRule。如果此条件返回 true,则将查看下一个条件。

RewriteCond %{REQUEST_FILENAME} !-f

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

RewriteCond %{REQUEST_FILENAME} !-d

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

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

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

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

批判:

MVC 框架的通常重写尝试尽可能提高性能。您的重写条件都必须经过评估才能成功重写。仅当任何 RewriteCond 返回 false 时才会停止。每个被重写的请求都要经过大量的 CPU 密集型测试。首先是 RewriteRule 正则表达式,然后是第一个 RewriteCond 中的正则表达式,然后是文件系统上的两个硬盘测试文件是否存在。

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

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

改进:

RewriteEngine on  
RewriteCond %{REQUEST_FILENAME} -f [OR] 
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]  
RewriteRule ^.*$ index.php [L]

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

如果没有找到文件,第一个 RewriteRule 和 RewriteCond 不会触发,所以那里的 [L] 不会停止进程。所以第二个 RewriteRule 被执行。这个是无条件的,正则表达式和之前一样,匹配一切,重写为“index.php”。

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

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

于 2012-10-12T20:31:50.407 回答
2

试试这个:

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

和这个:

# BEGIN PunBB

# ----------------------------------------------------------------------
# Start rewrite engine
# ----------------------------------------------------------------------

<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 /forum/

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . rewrite.php [L]
</IfModule>


# ----------------------------------------------------------------------
# Better website experience for IE users
# ----------------------------------------------------------------------

# Force the latest IE version, in various cases when it may fall back to IE7 mode
# github.com/rails/rails/commit/123eb25#commitcomment-118920
# Use ChromeFrame if it's installed for a better experience for the poor IE folk

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        BrowserMatch MSIE ie
        Header set X-UA-Compatible "IE=Edge,chrome=1" env=ie
    </IfModule>
</IfModule>

<IfModule mod_headers.c>
    # Because X-UA-Compatible isn't sent to non-IE (to save header bytes),
    # We need to inform proxies that content changes based on UA
    Header append Vary User-Agent
    # Cache control is set only if mod_headers is enabled, so that's unncessary to declare
</IfModule>


# ----------------------------------------------------------------------
# UTF-8 encoding
# ----------------------------------------------------------------------

# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8

# Force UTF-8 for a number of file formats
AddCharset utf-8 .html .css .js .xml .json .rss


# ----------------------------------------------------------------------
# A little more security
# ----------------------------------------------------------------------

# Do we want to advertise the exact version number of Apache we're running?
# Probably not.
## This can only be enabled if used in httpd.conf - It will not work in .htaccess
# ServerTokens Prod


# "-Indexes" will have Apache block users from browsing folders without a default document
# Usually you should leave this activated, because you shouldn't allow everybody to surf through
# every folder on your server (which includes rather private places like CMS system folders).
<IfModule mod_autoindex.c>
    Options -Indexes
</IfModule>

# END PunBB
于 2012-10-12T19:30:57.217 回答