【问题标题】:.htaccess rewrite and redirect two types of urls.htaccess 重写和重定向两种类型的 url
【发布时间】:2015-08-26 16:36:36
【问题描述】:

我正在尝试使用 .htacces 重写创建干净的 URL。我有两种类型的网址:

  1. site.com/page.php?page=something
  2. site.com/something.php

我需要它们都只是 site.com/something,从丑陋的网址重定向到漂亮的网址。所以现在我有以下规则,它们不能一起工作,我完全坚持重定向。

Options -Multiviews
RewriteEngine On
RewriteBase /

# page.php?page=about to about
RewriteRule ^([^/.]+)?$ /page.php?page=$1 [NC,L]

# something.php to something
RewriteRule ^([^/.]+)?$ $1.php [NC,L]

将不胜感激任何帮助。提前致谢。

【问题讨论】:

  • 服务器可以通过在第一条规则上使用RewriteCond 检查%{QUERY_STRING} 来判断使用哪个。
  • @PanamaJack 像RewriteRule ^([^/.]+)\.php?$ /page.php?page=$1 [NC] 这样的规则因为同样的原因不起作用?我可以将 /page.php?page=something 重写为 something.html 但不能重写为 something.php
  • @PanamaJack 不用担心,只是想帮助澄清一下,我最初的想法和你一样。

标签: .htaccess mod-rewrite redirect


【解决方案1】:

您的示例中有一些不正确的地方:

  • 您不能检查RewriteRule 中的查询字符串,只能在RewriteCond 中检查
  • 您的 RewriteRule 行是向后的 - 第一部分是 URL 的正则表达式匹配,第二部分是您想要的。
  • 您需要将[R] 规则作为重写的一部分来执行重定向,否则它只会“重写”服务器看到的 URL 而不会更改实际 URL。

这是您第一次重写的示例,将/page.php?page=foo 重定向到/foo。您首先需要一个RewriteCond 来检查%{QUERY_STRING} 变量以查看其中是否包含page=...。我们可以使用字符匹配 ([^&]*) 来获取所有不是 & 符号的字符并存储在匹配组中。接下来我们为page.php 执行RewriteRule(请注意,我们不需要前导/,因为RewriteBase 并且. 已转义)。如果此处有匹配项,您希望从 RewriteCond 重定向到匹配组 - 它使用 %1 而不是 $1 引用,就像它来自 RewriteRule 一样。您还需要在重定向的末尾附加一个?,它告诉Apache 删除查询字符串,这样您就不会以/foo?page=foo 结尾。最后,您将需要[R=301] 来执行 HTTP 状态代码为 301 的重定向。[L] 表示这是 Last 规则,如果有匹配项则要处理。

RewriteEngine On
RewriteBase /

# page.php?page=about to about
RewriteCond %{QUERY_STRING} page=([^&]*) [NC]
RewriteRule page\.php /%1? [R=301,L]

您的第二次重写更接近,但与第一次一样,逻辑是倒退的。您希望第一部分匹配*.php,然后第二部分表示重定向到/$1。同样,您将需要 [R-301] 进行重定向。

# something.php to something
RewriteRule (.*)\.php$ $1 [R=301,L]

您可以在 http://htaccess.madewithlove.be/ 上进行测试。

使用http://example.com/page.php?page=foo,重定向到http://example.com/foo

1       RewriteEngine On    
2       RewriteBase /   
3       # page.php?page=about to about  
4       RewriteCond %{QUERY_STRING} page=([^&]*) [NC]   
            This condition was met
5       RewriteRule page\.php /%1? [R=301,L]    
            This rule was met, the new url is http://example.com/foo    
            Test are stopped, because of the R in your RewriteRule options. 
            A redirect will be made with status code 301

使用http://example.com/foo.php 重定向到http://example.com/foo

1       RewriteEngine On    
2       RewriteBase /   
3       # page.php?page=about to about  
4       RewriteCond %{QUERY_STRING} page=([^&]*) [NC]   
            This condition was not met
5       RewriteRule page\.php /%1? [R=301,L]    
            This rule was not met because one of the conditions was not met
6       # something.php to something    
7       RewriteRule (.*)\.php$ /$1 [R=301,L]    
            This rule was met, the new url is http://example.com/foo    
            Test are stopped, because of the R in your RewriteRule options. 
            A redirect will be made with status code 301

【讨论】:

  • 我认为您不了解 OP 的问题。有 2 种不同的格式正试图制作成干净的 URL。问题是你不能两者兼得。 OP的代码单独没有问题,只是不能同时使用这两个规则,这是他们想要的。
  • @PanamaJack 你绝对可以两者兼得,看看我的回答。第一条规则有一个RewriteCond 并检查page= 的查询字符串。如果有匹配,它会重定向。如果不匹配,则处理下一条规则并仅使用 PHP 文件名重定向到“干净”的 url。您显然需要额外的规则来处理干净的 URL,但重定向工作正常 :)
  • @doublesharp 谢谢,重定向真的很好:)
  • @doublesharp,那么也许我误解了被问到的内容。因为我假设问题在浏览器中使用www.example.com/something,而不是real URL。因此,如果是这种情况,OP 示例中的第一条规则将始终在第二条规则之前运行。
  • @PanamaJack 如果您正在查看问题中的示例,那么您将是正确的,但就像我在回答中提到的那样,它们对于 OP 试图做的事情是倒退的。希望是从“丑陋”的 URL(其中包含 php 文件名)重定向到“干净”的 URL,例如 /about。将有额外的规则将/about 传递到index.php 或类似于实际处理请求的规则。
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 2016-09-28
  • 2013-01-27
  • 1970-01-01
  • 1970-01-01
  • 2017-06-16
  • 2013-12-21
  • 2015-03-04
相关资源
最近更新 更多