使用 mod_rewrite 将 301 重定向 get vars 到新的干净 URL
更新:解决方案在底部。
我最近从使用 index.php?p=page_name&o=temporary_override
等设置转为使用 /page_name/temporary_override
等干净的网址。临时覆盖只是为了让我可以在网站构建时看到网站更改的结果。
我目前将 mod_rewrite 设置为:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
它将捕获“子目录”,然后 PHP 从 GHPAGE $_GET var 解析 URL。我想要的是设置 301 重定向,以便任何使用 index.php?p=something&o=something_else 的人都将被重定向到 /something/something_else。知道我怎样才能做到这一点吗?该p& o 可以按任何顺序出现,并且其中之一可能不存在。
编辑:好的,在 @Jon-Lin、@dambrisco 和 @anubhava 的帮助下,我已经更接近了。我的 .htaccess 文件现在看起来像:
RewriteEngine On
#Base Directory
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^index\.php$ /%4/%5 [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^index\.php$ /%4 [R=301,L]
#Remove index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ / [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
它现在正在重定向,但还没有到达需要去的地方。 root/test/index.php?p=test&o=override
现在重定向到 root/test/override?p=test&o=override
。更接近,但我不知道如何摆脱添加到 URL 的 GET 变量,也不知道为什么它重定向到根目录而不是 RewriteBase 目录。
编辑:
它现在可以正确重定向,但由于某种原因,它从等式中删除了 /test/ RewriteBase 文件夹。 http://www.domain.com/test/index.php?p=page1&o=operation
正在重定向到 http://www.domain.com/page1/operation
。新的.htaccess 文件如下:
RewriteEngine On
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^ /%4/%5? [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^ /%4? [R=301,L]
#if index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ /$ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
谢谢大家。问题已经解决了。最终的 .htaccess 如下供参考。
RewriteEngine On
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^ %4/%5? [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^ %4? [R=301,L]
#if index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ ? [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
UPDATE: Solution at bottom.
I recently switched from using a set up such as index.php?p=page_name&o=temporary_override
and switched to clean urls such as /page_name/temporary_override
. The temporary override is just so I can see the results of the site changes while it's being built.
I currently have mod_rewrite set to:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
Which will capture the "subdirectories" and then PHP parses the URL from the GHPAGE $_GET var. What I want is to set up a 301 redirect so that anyone using index.php?p=something&o=something_else will get redirected to /something/something_else. Any idea how I can accomplish this? The p & o may come in any order and one or the other may not exist.
EDIT: Ok, after help from @Jon-Lin, @dambrisco, and @anubhava, I have gotten closer. My .htaccess file now looks like:
RewriteEngine On
#Base Directory
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^index\.php$ /%4/%5 [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^index\.php$ /%4 [R=301,L]
#Remove index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ / [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
It is now redirecting, but not quite where it needs to go. root/test/index.php?p=test&o=override
now redirects to root/test/override?p=test&o=override
. Closer, but I can't figure out how to get rid of the GET vars which are being added to the URL or why it's redirecting to the root directory instead of to the RewriteBase directory.
EDIT:
It's now redirecting properly, but for some reason it's dropping the /test/ RewriteBase folder from the equation. http://www.domain.com/test/index.php?p=page1&o=operation
is getting redirected to http://www.domain.com/page1/operation
. New .htaccess file is below:
RewriteEngine On
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^ /%4/%5? [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^ /%4? [R=301,L]
#if index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ /$ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
Thanks everyone. Question has been solved. Final .htaccess is below for reference.
RewriteEngine On
RewriteBase /test/
#if 2 GET Vars
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^ %4/%5? [R=301,L]
#if 1 GET Var
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /([^/]+/)*(index\.php)?\?[op]=(.+)\ HTTP\/
RewriteRule ^ %4? [R=301,L]
#if index.php
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*index\.php\ HTTP\/
RewriteRule ^index\.php$ ? [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
将其添加到 htaccess 中的某个位置:
如果您想涵盖没有“temporary_override”的情况,也请添加以下内容:
在
/%4/%5
末尾以删除查询字符串。并从/%4/%5
中删除前导/
,以防止其重写到根目录。因此,例如,您的规则之一应如下所示:Add this somewhere in your htaccess:
And if you want to cover the case where there's no "temporary_override", add this too:
Add a
?
at the end of/%4/%5
to get rid of the query string. And remove the leading/
from/%4/%5
to keep it from rewriting to the root. So, for example, one of your rules should look like this:您将需要使用以下内容:
这样,
example.com/page_name
就会在内部传递给index.php?p=page_name
和example。 com/page_name/operation
被传递到index.php?p=page_name&o=operation
。乔恩·林的回答似乎做了相反的事情,这是我昨晚没有注意到的。除了为了避免与您可能拥有的其他规则发生冲突(只是为了澄清)之外,不需要任何 RewriteCond。
You're going to want to use the following:
This way,
example.com/page_name
gets internally passed toindex.php?p=page_name
andexample.com/page_name/operation
gets passed toindex.php?p=page_name&o=operation
. Jon Lin's answer seems to have been doing the opposite, which I hadn't noticed last night.There shouldn't be any need for any RewriteConds except to avoid conflict with other rules that you might have, just to clarify.
您的 RewriteRule 行中的第 2 行更改应以
?
结尾,如下所示:Change 2 of your RewriteRule lines should end with
?
like this: