【问题标题】:htaccess pretty urls not workinghtaccess 漂亮的网址不起作用
【发布时间】:2017-04-06 14:24:03
【问题描述】:

文件夹结构:

- 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/ - 工作正常,但后来我尝试添加漂亮的 url,例如在我的 customers.php - localhost:8080/app/customers.php?id=5 更改为 localhost:8080/app/customers/id/5

htaccess 添加新行:

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

它不起作用,它总是返回500 Internal Server Error可能有问题吗?

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

【问题讨论】:

  • /id/(.*) 将始终匹配customers/php?**id**,因此您的规则将始终循环
  • 那么我该如何更改适用于我的情况的那条线?
  • 对不起,我对这个假设太仓促了,问题不在于那一行,问题是您的第一条规则,它将始终匹配,因此始终将 /views/ 添加到您的 URL 的开头. htaccess 规则非常容易搞砸。在我试图很好地回答这个问题之前,我需要了解更多。
  • 这是否意味着您想要 app 显示在您的实时网站的网址中?
  • 是的,我要展示的应用

标签: apache .htaccess mod-rewrite


【解决方案1】:

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

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

【讨论】:

  • 是的,大多数 PHP webapps/frameworks 也重写为 index.php,它将加载所有必需的代码,包括任何路由
【解决方案2】:

又是一个裂缝。

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 标志。也为 404 设置一个 ErrorDocument。

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

【讨论】:

    【解决方案3】:

    请参考问题How to make Clean URLs

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

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

    【讨论】:

      【解决方案4】:

      我自己尝试了您的结构和 .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
      

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

      这是由之前的 2 条规则之一引起的(删除它们可以解决问题),因此您可能需要更改它们。

      【讨论】:

        【解决方案5】:

        这就是你想要的:

        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]
        

        【讨论】:

          【解决方案6】:

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

          但是,由于您的问题似乎更多地是关于为什么这不起作用而不是关于您应该如何做,所以这里是对正在发生的事情的解释。

          我将使用这些 URL 作为示例:

          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 将匹配任何不是文件、不是目录且位于 localhost:8080 的 URL。

          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 语句仅适用于它们之后的第一个 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
          

          这里有一些问题。首先,由于您不要求 URL 以 /id/ 开头,因此该规则将始终匹配包含 /id/ 的 URL,即使您已经重写了 URL。如果您使用^/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 规则可能令人难以置信的混乱。

          【讨论】:

            猜你喜欢
            • 2015-10-17
            • 2012-03-07
            • 1970-01-01
            • 1970-01-01
            • 2016-02-14
            • 1970-01-01
            • 1970-01-01
            • 2012-01-10
            • 2012-06-05
            相关资源
            最近更新 更多