htaccess漂亮的网址不工作

时间:2016-11-22 19:12:04

标签: apache .htaccess mod-rewrite

文件夹结构:

- assets
  - all css / js
- calsses
  - all models, db ant etc
- views
  - admin
  - app
    - index.php
    - customers.php
    .......

我的.htaccess

RewriteEngine on

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

RewriteCond %{HTTP_HOST} ^(www.)?localhost:8080$

RewriteRule ^(.*)$ /views/$1
RewriteRule ^(/)?$ /views/index.php [L]

地址:localhost:8080/app/ - 工作正常,但我尝试在我的customers.php - localhost:8080/app/customers.php?id=5更改为localhost:8080/app/customers/id/5

中添加漂亮的网址

htaccess添加了新行:

RewriteRule /id/(.*) customers.php?id=$1

它无法正常工作,它总是返回 500内部服务器错误可能有问题?

加上需要没有.php扩展的所有网址

6 个答案:

答案 0 :(得分:6)

您必须为每个规则添加这些条件。你最好只重写所有内容,比如views/router.php,然后使用PHP包含不同的控制器,或者在URL无效时提供404。

RewriteRule !^views/router\.php$ views/router.php [NS,L,DPI]

答案 1 :(得分:2)

请参阅问题How to make Clean URLs

我认为这就是你所需要的。

您可以使用RewriteRule ^(.*)$ index.php [QSA,L]

答案 2 :(得分:2)

我同意Walf的看法,通过路由器类处理路由比使用.htaccess重定向更好(特别是从长远来看!)。

然而,由于你的问题似乎更多的是关于为什么这不起作用而不是你应该怎么做,这里是对正在发生的事情的解释。

我将使用这些网址作为示例:

localhost:8080
localhost:8080/app
localhost:8080/app/customers/id/5

你的第一条规则:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} ^(www.)?localhost:8080$
RewriteRule ^(.*)$ /views/$1

如您所愿,此RewriteRule将匹配任何不是文件的URL,而不是目录,并将其设置为localhost:8080。

localhost:8080 # not matched because it leads to a directory. 
localhost:8080/app -> localhost:8080/views/app
localhost:8080/app/customers/id/5 -> localhost:8080/views/app/customers/id/5

你的下一条规则:

RewriteRule ^(/)?$ /views/index.php [L]

重要的是要意识到RewriteCond语句仅适用于跟随它们的 first RewriteRule,因此这里检查的所有内容都是路径。

旁注:^(/)?$,因为您未使用$1,可以简化为^/?$

localhost:8080 -> localhost:8080/views/index.php
localhost:8080/views/app # not matched
localhost:8080/views/app/customers/id/5 # not matched

当指定L标志时,Apache将立即停止当前的迭代并从顶部再次开始匹配。 The documentation is badly worded。因此,localhost:8080/views/index.php将通过第一个规则运行,无法匹配,运行此规则,无法匹配,然后因为没有其他规则可以检查(还)将不会进行重写。

现在让我们看一下添加损坏规则时会发生什么。

RewriteRule /id/(.*) customers.php?id=$1

这里有一些问题。首先,由于您不要求网址以/id/开头,因此规则将始终与包含/id/的网址匹配,即使您已经重写了网址。如果您使用^/id/(.*)对此进行了修改,那么您仍然会遇到问题,因为重写RegEx被测试的字符串会删除前导斜杠。最后也是最重要的是,根目录中不存在customers.php

localhost:8080/views/index.php # not matched
localhost:8080/views/app # not matched
localhost:8080/views/app/customers/id/5 -> localhost:8080/customers.php?id=5

这是您当前文件中的最后一条规则,所以现在Apache将重新开始。您的目录中不存在customers.php,因此会将其重写为views/customers.php。没有其他规则匹配,但URL已更改,因此Apache将重新开始,因为/views/customers.php不存在,它将被重写为/views/views/customers.php ...此模式将重复,直到达到最大值迭代限制和Apache响应500错误。

你可以通过以下几种方式解决。这是我的首选方法,但前提是你不能使用路由器。

RewriteEngine on

# Rewrite the main page, even though it is a directory
RewriteRule ^/?$ views/index.php [END]

# Don't rewrite any existing files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .? - [S=999,END]

RewriteRule ^app/?$ views/app/index.php [END]
RewriteRule ^app/id/(.*)$ views/app/customers.php?id=$1 [END]

TL; DR 使用基于PHP的路由器。 .htaccess规则可能令人难以置信。

答案 3 :(得分:0)

又一次破解。

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{HTTP_HOST} !^(?:www\.)?localhost:8080$ [OR]
RewriteCond $0 =views
RewriteRule [^/]* - [END]

RewriteRule ^(app|admin)/([^/]+) views/$1/$2.php [DPI,END]
RewriteRule ^(app|admin)/?$ views/$1/index.php [DPI,END]

如果您的Apache较旧,则可能必须使用L而不是END标记。也为404s设置ErrorDocument。

不要使用查询字符串,只需在PHP中解析$_SERVER['REQUEST_URI'],例如首先在/上展开它。然后,您将拥有原始漂亮网址的所有参数。您可以在include中执行该部分,以便每个控制器可以重用相同的代码。

答案 4 :(得分:0)

我自己尝试了你的结构和.htaccess文件,并在apache日志中找到了无限循环。我打赌你有这样的事情:

Mon Nov 28 19:57:32.527765 2016] [core:error] [pid 10] [client 172.18.0.1:35048] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

我可以通过添加最后一条规则来修复它:

RewriteRule id/(.*) /views/app/customers.php?id=$1

匹配时不需要前导/,目标需要完整路径。请注意,我在网址http://localhost:8080/id/123上获得了id double(例如123/123)。

这是由之前的两条规则之一引起的(删除它们会修复它),因此您可能需要更改它们。

答案 5 :(得分:0)

这是你想要的:

RewriteEngine On
RewriteBase /app/

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

RewriteRule ^\/?$ views/index.php [L]
RewriteRule ^([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)\/([a-zA-Z0-9]+)\/?$ views/$1.php?$2=$3 [L]
RewriteRule ^([a-zA-Z0-9]+)\/?$ views/$1.php [L]