https://www.example.com/index.php?/my-seo-friendly-uri
Этот URL-адрес содержит строку запроса, поэтому для его соответствия требуется немного другое правило. Шаблон RewriteRule
соответствует только URL-пути (в данном случае просто index.php
). Строка запроса доступна в своей собственной переменной.
Добавьте следующее перед вашими существующими директивами (в дополнение к директиве, которая соответствует /index.php/my-seo-friendly-url
- которая передается как path-info ) :
# 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]
Захвачена строка запроса (2-е условие), а обратная ссылка (%1
) используется для создания перенаправления.
Первое условие, проверяющее соответствие REDIRECT_STATUS
Переменная окружения требуется для предотвращения перенаправления l oop, так как вы, похоже, используете метод строки запроса для маршрутизации URL-адресов codeigniter при последующем переписывании. Переменная REDIRECT_STATUS
env пуста при первоначальном запросе, но после первого успешного перезаписи установлена в «200» (как в состоянии «HTTP OK 200»).
Флаг QSD
(Apache 2.4+) ) требуется для удаления исходной строки запроса из перенаправленного запроса. Если вы все еще используете Apache 2.2, тогда добавьте ?
(пустую строку запроса) вместо строки substitution . ie. %1?
Сделав сопоставление для index.php
необязательно (ie. ^(index\.php)?$
), он также будет канонизировать URL-адреса, в которых пропущен index.php
, но при этом будет включена строка запроса (это может или не может быть в настоящее время проблемой). например. /?/my-seo-friendly-uri
.
Обратите внимание, что в настоящее время это 302 (временное) перенаправление (как и ваше существующее перенаправление). Измените это на 301 (постоянное) перенаправление, только когда вы подтвердите, что оно работает нормально. 301s постоянно кэшируется браузером, поэтому тестирование может быть проблематичным c.
Сводка
Ваш файл .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>
не требуется. (.*)
аналогична ^(.*)$
, так как регулярное выражение по умолчанию жадное. - Я изменил существующее перенаправление path-info (ie.
/index.php/foo
), чтобы также перенаправлять запросы только на /index.php
. Теперь для этого требуется дополнительное условие, чтобы избежать перенаправления l oop. Ваш фронт-контроллер CodeIgniter использует метод строки запроса для передачи /my-seo-friendly-url
бэкэнду (как используется в вопросе) , Однако вы установили $config['uri_protocol'] = 'REQUEST_URI';
- что противоречит этому (хотя это не обязательно должно быть проблемой). Однако, если вы используете метод REQUEST_URI
, вы можете удалить часть ?/$1
из конца последней строки RewriteRule
substitution . Например:
Например, из этого:
RewriteRule (.*) index.php?/$1 [L]
Для этого:
RewriteRule . index.php [L]