Первый (и неправильный) ответ - см. Ниже
Вы можете выполнить перенаправление с помощью следующих директив (в следующем порядке):
RewriteCond %{REQUEST_URI} ^index.php
RewriteRule ^index\.php/(.+)$ /$1 [R,L]
RewriteCond $1 !^(index.php|images|css|js|robots.txt)
RewriteRule ^(.*?)$ /index.php/$1 [L]
Сначала перенаправит все запросы, начинающиеся с index.php
, на соответствующий сокращенный URL-адрес, а затем тихо обработает index.php/etc
со вторым правилом.
РЕДАКТИРОВАТЬ - Пожалуйста, продолжайте читать!
Фактически, решение выше генерирует бесконечный цикл перенаправления, потому что Apache выполняет следующие действия (скажем, мы запрашиваем /index.php/abc
):
- первый
RewriteCond
совпадений
- Apache перенаправляет [R], то есть генерирует новый HTTP-запрос, к
/abc
/abc
первый сбой RewriteCond
/abc
соответствует второму RewriteCond
- Apache не перенаправляет, а переписывает этот URI (поэтому он делает «скрытый» запрос) в
/index.php/abc
. Мы снова в точке 1, это цикл.
Обратите внимание ...
- Используя флаг [L] (последнее правило), мы можем только сказать Apache не обрабатывать больше правил перезаписи, но только если текущее правило совпадает. Так как новый HTTP-запрос сделан, нет никакой информации о том, как перенаправление мы могли пройти через. Таким образом, в любое время одно из двух совпадений и в любом случае генерирует новый запрос (=> цикл)
- Использование флага [C] (правила цепочки) бессмысленно, поскольку Apache обрабатывает правило только в том случае, если совпадает предыдущее правило, а два наших правила взаимно исключают.
- Использование флага [NS] (not if subrequest) в правиле # 1 снова не вариант, поскольку он просто не применим к нашему случаю (см. Apache RewriteRule docs об этом)
- Установка переменных env не является опцией (увы), так как новый запрос выполняется на pt 2, тем самым уничтожая все переменные среды, которые мы установили.
Альтернативным решением может быть, например, переписать. /abc
, до /index.php?path=abc
. Это делается по этим правилам (пожалуйста, удалите аналогичное правило RedirectMatch перед добавлением этих):
RedirectMatch ^/index\.php(/.*) $1
RewriteCond %{REQUEST_URI} !^/(index.php|images|css|js|robots.txt|favicon.ico)
RewriteRule ^(.+) /index.php?path=$1 [L,QSA]
Я не знаю внутренностей скриптов CodeIgniter, но, как и большинство скриптов MVC, он будет читать $_REQUEST['PATH_INFO']
, чтобы понять, какая страница запрашивается. Вы можете немного изменить код, который распознает страницу следующим образом (я предположил, что путь к странице хранится в $page
var):
$page = $_REQUEST['PATH_INFO'];
if(isset($_GET['path']) && strlen($_GET['path'])) $page = $_GET['path']; // Add this line
Это не сломает предыдущий код и не выполнит то, что вы просили.