Перенаправити всі на index.php за допомогою htaccess


131

Я пишу просту основу MVC-ish на базі 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 ?
Технох

До папки, в якій знаходиться файл htaccess, кореневого каталогу фреймворка. У моєму прикладі повернутися до каталогу mvc
David Ericsson

Відповіді:


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 для визначення контролера і дій , які необхідно виконати.


Якщо ви хочете, щоб весь шебанг встановився в підкаталозі, наприклад, /mvc/або /framework/найменш складний спосіб зробити це - трохи змінити правило перезапису, щоб врахувати це.

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

І переконайтеся, що ваш файл index.phpзнаходиться у цій папці, а .htaccessфайл - у корені документа.


Альтернатива$_GET['path'] (оновлено лютий '18 та січень '19)

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

Це RewriteRuleтрохи спрощує те , що вам не потрібно створювати параметр шляху (це означає, що оригінал ОП тепер 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.


1
це має бути index.php? path = $ 1
Jacek Pietal

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
Використовуйте *замість +цього шаблону, якщо ви хочете переспрямувати і сам кореневий шлях.
Мір-Ісмаїлі

15

Ви можете використовувати щось подібне:

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

Це переспрямує кожен запит до index.php кореневої директорії. Зауважте, що він також буде перенаправляти запити на наявні файли, такі як зображення, файли javascript або таблиці стилів.


1
Це рішення майже працювало для мене. Я продовжував отримувати "AH00124: Запит перевищив ліміт 10 внутрішніх переадресацій". Я раніше додав "RewriteRule ^ index \ .php - [L]" і це працює чудово!
Фредстер

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 )


0

Після цього не забудьте змінити тег прив’язки додому

Приклад:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>

Завжди не забудьте змінити тег <a>.
Колінз Бенсон

2
Що означає Після того, як не змінити тег, додому означає?
Енріко Марія Де Анджеліс

0

на всякий випадок, коли ви все ще цікавились, як перенаправити весь запит, або якщо каталог існує (для основних папок і файлів основної бази) на обробник індексу Framework, після деяких спроб помилок / успіху просто помітили, що мені просто потрібно змінити 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]

Це працювало на мене, як на чарівність

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.