我有一个旧项目,它有一些奇怪的问题。其CodeIgniter项目(版本2.X(。
谷歌正在用index.php?索引我们的网址。下面是一个示例
https://www.website.com/index.php?/my-seo-friendly-uri
我可以从上面的网址看到我的页面,还有 2 个变体,如下所示
https://www.website.com/index.php/my-seo-friendly-uri
https://www.website.com/my-seo-friendly-uri
我们在整个网站中使用了https://www.website.com/my-seo-friendly-uri
。
我的问题是如何将https://www.website.com/index.php?/my-seo-friendly-uri
和https://www.website.com/index.php/my-seo-friendly-uri
重定向到https://www.website.com/my-seo-friendly-uri
?
我已经做过的事情
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^index.php/(.*)$ /$1 [R=302,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
这会index.php
重定向到普通 URL,但index.php?
版本的 url 仍未重定向
在我的config.php
中,我有以下设置
$config['index_page'] = '';
$config['uri_protocol'] = 'REQUEST_URI';
>https://www.example.com/index.php?/my-seo-friendly-uri
此 URL 包含一个查询字符串,因此需要稍微不同的规则才能匹配它。RewriteRule
模式仅与 URL 路径匹配(在本例中仅index.php
(。查询字符串在其自己的变量中可用。
在现有指令之前添加以下内容(除了与/index.php/my-seo-friendly-url
匹配的指令 - 作为路径信息传递(:
# Redirect URLs of the form "/index.php?/my-seo-friendly-uri"
# And "/?/my-seo-friendly-uri"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(/.*)
RewriteRule ^(index.php)?$ %1 [QSD,R=302,L]
捕获查询字符串(第二个条件(,并使用反向引用(%1
(来构造重定向。
为了防止重定向循环,需要检查REDIRECT_STATUS
环境变量的第一个条件,因为您似乎正在使用查询字符串方法来路由代码点火器 URL。REDIRECT_STATUS
env var 在初始请求中为空,但在第一次成功重写后设置为"200"(如 200 OK HTTP 状态(。
需要QSD
标志 (Apache 2.4+( 才能从重定向请求中丢弃原始查询字符串。如果您仍在使用 Apache 2.2,请将?
(空查询字符串(附加到替换字符串中。即。%1?
通过将index.php
匹配设置为可选(即。^(index.php)?$
(,它还会将省略index.php
但仍然包含查询字符串(目前可能是也可能不是问题(的 URL 规范化。例如。/?/my-seo-friendly-uri
.
请注意,这目前是 302(临时(重定向(与您现有的重定向一样(。只有在确认它工作正常后,才将其更改为 301(永久(重定向。 301 由浏览器永久缓存,因此可能会使测试出现问题。
总结
您的.htaccess
文件应如下所示:
RewriteEngine On
# Query string...
# Redirect URLs of the form "/index.php?/my-seo-friendly-uri"
# And "/?/my-seo-friendly-uri"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(/.*)
RewriteRule ^(index.php)?$ %1 [QSD,R=302,L]
# Path-Info...
# Redirect URLs of the form "/index.php/my-seo-friendly-uri"
# Also handles "/index.php" only
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index.php(?:/(.*))?$ /$1 [R=302,L]
# CodeIgniter Front-controller
# (NB: Using query string method to pass the URL)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?/$1 [L]
附加说明...
- 不需要
<IfModule>
包装器。 (.*)
与^(.*)$
相同,因为正则表达式默认是贪婪的。- 我已经修改了您现有的路径信息重定向(即。
/index.php/foo
( 也仅重定向/index.php
请求。现在,这需要一个附加条件来避免重定向循环。 CodeIgniter 前端控制器正在使用查询字符串方法将
/my-seo-friendly-url
传递到后端(如问题中所述(。但是,您已经设置了$config['uri_protocol'] = 'REQUEST_URI';
- 与此相矛盾(尽管不一定是问题(。但是,如果使用REQUEST_URI
方法,则可以从最终替换字符串的末尾删除?/$1
RewriteRule
部分。例如:例如,从这个:
RewriteRule (.*) index.php?/$1 [L]
对此:
RewriteRule . index.php [L]
使用 .htaccess................
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
<IfModule mod_php5.c>
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
<IfModule !mod_php5.c>
RewriteRule ^(.*)$ index.php?/$1 [L]
</IfModule>
</IfModule>