Перенаправить все на index.php с помощью htaccess

131

Я пишу простой MVC-фреймворк на основе PHP. Я хочу, чтобы этот фреймворк можно было установить в любой каталог.

Мой PHP-скрипт захватывает URI запроса и разбивает его на сегменты. Он делает сегмент 1 контроллером, а сегмент 2 действием. Все идет нормально, когда я делаю это:

http://www.example.com/mvc/module/test/

Он перейдет к конкретному контроллеру модуля и методу. Теперь у меня есть контроллер по умолчанию, домашний контроллер, который находится в домашней папке.

Теперь, когда я напрямую обращаюсь к этой папке http://www.example.com/mvc/home/, будет отображаться 403 запрещено, потому что эта папка существует, вместо этого она также должна вернуться на http://www.example.com /mvc/index.php

Если бы я установил фреймворк в другую папку, скажем, фреймворк папки, он должен перенаправить обратно на http://www.example.com/framework/index.php

Я хотел бы перенаправить каждую папку и файл php обратно в index.php, оставив все остальное как есть.

Моя первая проблема, с которой я столкнулся, заключалась в том, что он никогда не перенаправляется в нужную папку, всегда в корневую папку домена.

Вот что я пробовал:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
Дэвид Эрикссон
источник
Просто чтобы убедиться, что я правильно понимаю ваш вопрос: вы хотите перенаправить каждый запрос в корень index.php или вы хотите перенаправить каждый запрос, сделанный в эту конкретную папку index.php ?
Technoh
В папку, в которой находится файл htaccess, корневой каталог фреймворка. В моем примере возврат к каталогу mvc
Дэвид Эрикссон

Ответы:

259

Ваше правило перезаписи выглядит почти нормально.

Сначала убедитесь, что ваш .htaccessфайл находится в корне вашего документа (в том же месте, что иindex.php ), иначе он повлияет только на подпапку, в которой он находится (и любые подпапки в ней - рекурсивно).

Затем внесите небольшое изменение в свое правило, чтобы оно выглядело примерно так:

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

На данный момент вы просто сопрягая на .который один экземпляр любого характера, необходимо , по крайней мере , .*чтобы соответствовать любому количеству экземпляров любого характера.

$_GET['path']Переменный будет содержать структуру каталогов подделки, так /mvc/module/test, например, которые затем можно использовать в index.php для определения контроллера и действий , которые необходимо выполнить.


Если вы хотите, чтобы весь shebang был установлен в подкаталоге, например, /mvc/или /framework/наименее сложный способ сделать это, это немного изменить правило перезаписи, чтобы принять это во внимание.

RewriteRule ^(.*)$ /mvc/index.php?path=$1 [NC,L,QSA]

И убедитесь, что вы index.phpнаходитесь в этой папке, пока .htaccessфайл находится в корне документа.


Альтернатива$_GET['path'] (обновлено февраль 18 и январь 19)

На самом деле нет необходимости (и даже сейчас) устанавливать путь как $_GETпеременную, многие фреймворки будут полагаться на $_SERVER['REQUEST_URI']получение одной и той же информации - обычно для определения того, какой контроллер использовать, - но принцип тот же.

Это RewriteRuleнемного упрощает, так как вам не нужно создавать параметр пути (что означает, что оригинал OP теперь RewriteRule будет работать):

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]

Однако правило установки в подкаталоге по-прежнему применяется, например

RewriteRule ^.*$ /mvc/index.php [L,QSA]



Флаги:

NC = Без регистра (регистр не учитывается, в действительности нет необходимости, поскольку в шаблоне нет символов)

L = Последний (он перестанет перезаписывать после этой перезаписи, поэтому убедитесь, что это последняя вещь в вашем списке перезаписей)

QSA= Строка запроса Добавить, на случай, если у вас есть что-то вроде ?like=penguinsтого, что вы хотите сохранить и передать в index.php.

CD001
источник
1
это должно быть index.php? path = $ 1
Яцек Пьетал
1
@Prozi нет , если вы находитесь в поддиректории и index.php находится в DOCROOT, то вам нужно ведущий / - с Options +Indexesи index.php включены в DirectoryIndexвы могли бы уйти от index.php в целом и просто использовать /?path=$1Это справедливо , когда выполнение перезаписи через .htaccess, а не в <Directory>директиве типа httpd-vhosts.conf .
CD001
Если вы используете это и полагаетесь на $ _GET ['path'], у вас будут проблемы в случае перехода на сервер nginx ...
barell
3
Хороший пост! Стоит отметить, что пользователь может перезаписывать$_GET['path'] если добавит path=whateverк URL.
rybo111
1
@Liviuge - правда, но изначально я проходил весь путь, $_GETпоэтому это потребовалось (.*)... это забавно, но RewriteRule, который OP использовал 6 лет назад, тогда для них не работал - но с тем, как архитектура MVC эволюционировал с помощью PHP (как я добавил в обновленной версии от 18 февраля ), теперь это будет ... думаю, они опередили свое время :) /mvc/Конечно, по- прежнему нужен правильный путь к каталогу.
CD001
28

Чтобы перенаправить все, что не существует index.php, вы также можете использовать FallBackResourceдирективу

FallbackResource /index.php

Он работает так же, как ErrorDocumentесли вы запрашиваете несуществующий путь или файл на сервере, директива молча пересылает запрос наindex.php .

Если вы хотите перенаправить все ( including existant files or folders) на index.php, вы можете использовать что-то вроде следующего:

RewriteEngine on

RewriteRule ^((?!index\.php).+)$ /index.php [L]

Обратите внимание, что шаблон ^((?!index\.php).+)$ соответствует любому uri, за исключением того, что index.phpмы исключили путь назначения, чтобы предотвратить ошибку бесконечного цикла.

Амит Верма
источник
Но вы также можете использовать:DirectoryIndex index.php
Шао
1
Используйте *вместо +в шаблоне, если вы также хотите перенаправить сам корневой путь.
Mir-Ismaili
15

Вы можете использовать что-то вроде этого:

RewriteEngine on
RewriteRule ^.+$ /index.php [L]

Это перенаправит каждый запрос на index.php корневого каталога. Обратите внимание, что он также будет перенаправлять запросы для существующих файлов, таких как изображения, файлы javascript или таблицы стилей.

Technoh
источник
1
Это решение почти сработало для меня. Я продолжал получать "AH00124: запрос превысил лимит в 10 внутренних перенаправлений". Я добавил "RewriteRule ^ index \ .php - [L]" раньше, и он отлично работает!
Фредстер 02
11

Есть один «трюк» для этой проблемы, который подходит для всех сценариев, настолько очевидное решение, что вам придется попробовать его, чтобы поверить, что оно действительно работает ... :)

Вот...

<IfModule mod_rewrite.c>

   RewriteEngine On

   RewriteCond %{REQUEST_FILENAME}  -f [OR]
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)$ index.php [L,QSA]

</IfModule>

По сути, вы просите MOD_REWRITE перенаправлять index.phpзапрос URI всегда, когда файл существует, И всегда, когда запрошенный файл не существует !

Изучая исходный код MOD-REWRITE, чтобы понять, как он работает, я понял, что все его проверки всегда происходят после проверки, существует ли указанный файл или нет. Только после этого RegExони обрабатываются. Даже когда ваш URI указывает на папку, Apache будет принудительно проверять файлы индекса, перечисленные в его файле конфигурации.

Основываясь на этом простом открытии, стало очевидным, что простой проверки файла будет достаточно для всех возможных вызовов , поскольку мы дважды коснемся проверки наличия файла и направим оба результата в одну и ту же конечную точку, покрывая 100% возможностей.

ВАЖНО: Обратите внимание, что в скобках нет символа " / " index.php. По умолчанию MOD_REWRITE будет использовать папку, которую он установлен в качестве «базовой папки» для пересылки. Его прелесть в том, что это не обязательно должна быть «корневая папка» сайта, что позволяет этому решению работать наlocalhost/ и / или любой вложенной папки, в которой вы его применяете.

В конечном счете, некоторые другие решения, которые я тестировал ранее (те, которые, казалось, работали нормально), нарушили способность PHP «запрашивать» файл по его относительному пути, что является обломом. Быть осторожен.

Некоторые могут сказать, что это неэлегантное решение. Может быть, действительно, но что касается тестов, в нескольких сценариях, нескольких серверах, нескольких разных версиях Apache и т.д., это решение работало на 100% во всех случаях!

Хулио Марчи
источник
Спасибо, это устранило мою проблему, когда FallbackResource index.phpлиния работала на Mac (OS X 10.11), но не работала под Centos 7.5. Однако: например, это RewriteRuleтакже переписывает расположение файлов CSS. Поскольку мне нужно было перенаправлять только файлы PHP, я изменил правило на RewriteRule ^(.*)php$ index.php [L,QSA]. YMMV.
Laryx Decidua
1
Я счастлив, что это помогло. Вы правы, он нацелен на ВСЕ файлы, потому что вопрос был: « Перенаправить все на index.php с помощью htaccess ». Есть и другие, более элегантные способы перенаправления только файлов PHP, например RewriteRule ^(.*)\.php$ index.php [L,NE,QSA](для работы не требуются условия). В настоящее время, однако, я использую более недорогое правило: RewriteRule ^.+$ index.php [L,NE,QSA]которое может сочетаться с условиями RewriteCond %{REQUEST_FILENAME} !-fи RewriteCond %{REQUEST_FILENAME} !-d, или даже, RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)чтобы быть действительно конкретным.
Хулио Марчи
5

Глупый ответ, но если вы не можете понять, почему он не перенаправляет, проверьте, что для веб-папки включено следующее:

AllowOverride All

Это позволит вам запустить htaccess, который должен быть запущен! (есть альтернативы, но они не вызовут проблемы https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )

Antony
источник
0

Сделав это, не забудьте изменить свой тег привязки, домой

Пример:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>
Коллинза Бенсона
источник
Всегда не забывайте менять тег <a>.
Коллинз Бенсон
2
Что означает « Домой» после того, как вы не изменили тег ?
Энрико Мария Де Анджелис
0

на всякий случай вам все еще было интересно, как перенаправить весь запрос, если каталог существует (для основных папок и файлов структуры), в обработчик индекса инфраструктуры, после некоторых попыток ошибки / успеха я просто заметил, что мне просто нужно было изменить RewriteCond в .htaccess файл

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

в приведенном выше условии указано «не найденные файлы» и «не найденные каталоги», хорошо, а что, если просто удалить строку «не найден» (! -d) и закончиться чем-то вроде следующего:

RewriteEngine on
RewriteBase /framework/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /framework/index.php [L,QSA]

Это сработало для меня как шарм

AugustoM
источник