Использование mod_rewrite для перенаправления 301 для получения переменных на новые чистые URL-адреса

ОБНОВЛЕНИЕ: Решение внизу.

Недавно я отказался от настройки, такой как index.php?p=page_name&o=temporary_override, и переключился на чистые URL-адреса, такие как /page_name/temporary_override. Временное переопределение просто для того, чтобы я мог видеть результаты изменений сайта во время его создания.

В настоящее время у меня mod_rewrite установлен на:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?GHPAGE=$1 [L,QSA]

Который будет захватывать «подкаталоги», а затем PHP анализирует URL-адрес из переменной GHPAGE $_GET. Я хочу настроить перенаправление 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. Ближе, но я не могу понять, как избавиться от переменных GET, которые добавляются к URL-адресу, или почему он перенаправляется в корневой каталог, а не в каталог 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]

person mtylerb    schedule 08.02.2012    source источник


Ответы (3)


Добавьте это где-нибудь в свой htaccess:

RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /index\.php\?p=([^&]+)&o=(.+)\ HTTP
RewriteRule index.php /%2/%3 [R=301,L]

И если вы хотите охватить случай, когда нет «temporary_override», добавьте и это:

RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /index\.php\?p=(.+)\ HTTP
RewriteRule index.php /%2 [R=301,L]

Ближе, но я не могу понять, как избавиться от переменных GET, которые добавляются в URL-адрес, или почему он перенаправляется в корневой каталог, а не в каталог RewriteBase.

Добавьте ? в конце /%4/%5, чтобы избавиться от строки запроса. И удалите начальный / из /%4/%5, чтобы он не перезаписывался в корень. Так, например, одно из ваших правил должно выглядеть так:

RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ \/([^\/]+\/)*(index\.php)?\?[op]=([^&]+)&[op]=(.+)\ HTTP\/
RewriteRule ^index\.php$ %4/%5? [R=301,L]
person Jon Lin    schedule 08.02.2012
comment
Вы можете использовать RewriteRule ^index/.php$ /%2/%3 [R=301,L] - person anubhava; 08.02.2012
comment
Вы имеете в виду ^index\.php$ - мелкая придирка. - person Dan Ambrisco; 08.02.2012
comment
Кажется, ничего не делает. В настоящее время используется код @JonLin с добавлением @dambrisco для создания RewriteRule ^index\.php$ /%2/%3 [R=301,L]. При посещении сайта с index.php?p=l&o=override сайт не перенаправляется на /l/override. Благодарю за помощь, до сих пор. - person mtylerb; 08.02.2012
comment
После небольшого поиска и получения результата, который возвращает THE_REQUEST, он выглядит так: GET /test/index.php?p=test&o=override HTTP/1.0. Итак, я понимаю %{THE_REQUEST} ^([A-Z]{3,9})\ , но здесь я запутался. Следует ли экранировать «/» перед index.php, например \/index\.php? Я вижу, что cPanel избежала кучу «/» в других 301 редиректах для других доменов на моем сервере. Кроме того, \?p=([^&]+)&o=(.+)\ HTTP, это должно быть \?(p|o)=([^&]+)&(p|o)=(.+)\ HTTP(.{0,4})? Позволит ли это переменным get идти в любом порядке? Спасибо еще раз! - person mtylerb; 08.02.2012
comment
Потрясающе, почти. Я пропустил обновление к этому ответу. Теперь единственная проблема в том, что http://www.domain.com/test/index.php перенаправляет на http://www.domain.com/ вместо http://www.domain.com/test/. - person mtylerb; 09.02.2012
comment
RewriteRule ^index\.php$ /$ [L,R=301] должно быть указано RewriteRule ^index\.php$ /test/ [L,R=301] или RewriteRule ^index\.php$ ? [L,R=301], чтобы отразить изменения (удаление косой черты) в других правилах. - person Jon Lin; 09.02.2012

Вы захотите использовать следующее:

RewriteRule ^([^/]+)/?$ index.php?p=$1 [L,QSA]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?p=$1&o=$2 [L,QSA]

Таким образом, example.com/page_name передается внутри index.php?p=page_name, а example.com/page_name/operation передается index.php?p=page_name&o=operation. Ответ Джона Лина, кажется, делал противоположное, чего я не заметил прошлой ночью.

Не должно быть необходимости в каких-либо RewriteConds, кроме как во избежание конфликта с другими правилами, которые могут у вас быть, просто для уточнения.

person Dan Ambrisco    schedule 08.02.2012
comment
Если я правильно их читаю, они повлияют только на правильно введенные URL-адреса. Что я хочу сделать, так это 301 перенаправить старые грязные URL-адреса на новые чистые URL-адреса. Как в /?p=test&o=override 301=› /test/override. - person mtylerb; 09.02.2012
comment
Ах, мой плохой. Я неправильно понял проблему. Теперь ответ Джона Лина имеет гораздо больше смысла. Я взгляну на это позже, если это не было решено. - person Dan Ambrisco; 09.02.2012

Измените 2 строки вашего RewriteRule, чтобы они заканчивались на ? следующим образом:

#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]
person anubhava    schedule 08.02.2012
comment
Ближе, это работает, но теперь он меняет URL-адрес с /test/index.php?p=test&o=override на /?GHPAGE=test/override. РЕДАКТИРОВАТЬ: Неважно, он решил начать играть хорошо. Тем не менее, папка RewriteBase по-прежнему удаляется из уравнения. /test/index.php?p=test&o=override становится root/test/override/, хотя должно быть root/test/test/override/. Любые идеи? Я обновлю свой .htaccess выше. - person mtylerb; 09.02.2012