.htaccess mod_rewrite问题

时间:2010-03-23 12:16:52

标签: apache .htaccess

几乎在我工作的任何项目中,都会出现.htaccess的一些问题。我通常只找到最简单的解决方案,因为我对Apache,服务器等没有任何了解或理解。但这次我想我会问你们。

这是我(简化)设置中的文件和文件夹:

/modrewrite-test
    .htaccess
    /config
    /inc
    /lib
    /public_html
        .htaccess
        /cms
            /navigation
                index.php
                edit.php
            /pages
                index.php
                edit.php
        login.php
        page.php

“config”,“inc”和“lib”文件夹意味着从网站的根目录“隐藏”。我尝试通过在根目录中创建一个将用户重定向到“public_html”的.htaccess文件来实现此目的。 .htacess文件包含:

RewriteEngine On
RewriteRule   (.*) public_html/$1

这很完美。如果我在浏览器中输入“http://localhost/modrewrite-test/login.php”,我最终会出现在public_html / login.php中,这是我的意图。所以这很好。 “public_html”中的.htaccess文件包含:

RewriteEngine On

# Root
RewriteRule   ^$ page.php [L]

# Login
RewriteRule   ^(admin)|(login)\/?$ login.php [L]

# Page (if not a file/directory)
RewriteCond   %{REQUEST_FILENAME} !-d
RewriteCond   %{REQUEST_FILENAME} !-f
RewriteRule   ^(.*)$ page.php?url=$1 [L]

如果我尝试触及“http://localhost/modrewrite-test/”,第一次重写只会将我重定向到public_html / page.php。下一次重写只是为了方便用户尝试登录 - 所以如果他们尝试访问“http://localhost/modrewrite-test/admin”或“http://localhost/modrewrite-test/login”,他们最终会登录login.php文件。第三次和最后一次重写处理其余请求。如果我尝试达到“http://localhost/modrewrite-test/bla/bla/bla”,它只会将我重定向到public_html / page.php(使用'url'GET-variable set),而不是找到一个名为“la”的文件夹,其中包含一个名为“bla”的文件夹“等等。

所有这些工作都很完美,但是当我尝试在URL的末尾没有斜杠时达到“http://localhost/modrewrite-test/cms/navigation”时会出现一些小问题。当我尝试访问该页面时,浏览器会以某种方式重定向到“http://localhost/modrewrite-test/public_html/cms/navigation/”。显示正确的页面,但为什么会重定向并在URL中添加“public_html”部分?所需的行为是URL保持不变,并显示页面public_html / cms / navigation / index.php。

可以在http://highbars.com/modrewrite-test.zip

找到(简化)中的文件和文件夹

3 个答案:

答案 0 :(得分:3)

在尝试访问现有目录而没有斜线时,我遇到了与“奇怪”重定向相同的问题。在我的例子中,这个重定向是由 mod_dir Apache模块完成的。要禁用重定向,我使用了DirectorySlash指令。尝试在字符串后面输入 .htaccess 文件:

DirectorySlash Off

答案 1 :(得分:0)

RewriteBase可能有所帮助。在public_html / .htaccess中试试这个:

RewriteEngine On
RewriteBase /

答案 2 :(得分:0)

将以下内容添加到/modrewrite-test/.htaccess

RewriteBase /modrewrite-test

为了安全起见,我还要向/modrewrite-test/public_html/.htaccess添加相同的规则。我发现总是设置RewriteBase可以防止将来出现很多潜在的问题。但是,这意味着如果更改站点的URI结构,则可能需要更新值。

<强> 更新
我不认为这对您当前的文件夹结构是可行的。我认为问题是现有的子目录阻止重写规则被触发。请注意这种行为 - 由于这两个条件,在您处理不存在的文件和目录时一切正常:

RewriteCond   %{REQUEST_FILENAME} !-d
RewriteCond   %{REQUEST_FILENAME} !-f

但是,如果您尝试从现有子目录中打开任何索引文件,则会被重定向到.../public_html/...。由于您可以正确地打开/modrewrite-test/cms/navigation/edit.php,我只能假设某个Apache核心指令覆盖了该请求,该指令在文件夹URL的末尾添加了斜杠。请注意,如果每个URL都有一个结尾斜杠,一切正常(即Apache核心目录不需要“更正”您的URL,因此所有内容都会被您自己的重写规则重写)。

建议的解决方案(除非有人能提出更好的建议):

按如下方式更改/modrewrite-test/public_html/.htaccess

RewriteEngine On
RewriteBase /modrewrite-test

# Page (if not a file/directory)
RewriteCond   %{REQUEST_FILENAME} !-d
RewriteCond   %{REQUEST_FILENAME} !-f
RewriteRule   ^(.*)$ page.php?url=$1 [L]

然后从子文件夹中删除所有PHP文件并使用Front Controller pattern,即通过主page.php文件路由所有请求,并且不要在下面委派任何内容。

然后,您可以使用Factory pattern根据$ _GET ['url']的内容直接从主navigation/edit.php文件启动单个UI(即page.php)(确保正确消毒)。

更新#2:
这个other post on StackOverflow建议Zend框架使用的项目结构 - 它基本上显示了我上面提出的方法。无论您是否使用Zend Framework,它都是有价值的信息资产。