Piszę prosty framework MVC oparty na PHP. Chcę, aby ten framework mógł być zainstalowany w dowolnym katalogu.
Mój skrypt PHP pobiera żądanie uri i dzieli je na segmenty. Sprawia, że segment 1 jest kontrolerem, a segment 2 działaniem. Wszystko idzie dobrze, kiedy robię to:
http://www.example.com/mvc/module/test/
Przejdzie do konkretnego kontrolera modułu i metody. Teraz mam domyślny kontroler, kontroler domowy, który znajduje się w folderze home.
Teraz, gdy uzyskam bezpośredni dostęp do tego folderu http://www.example.com/mvc/home/ Zostanie wyświetlony kod 403 zabroniony, ponieważ ten folder istnieje, zamiast tego powinien również wrócić do http://www.example.com /mvc/index.php
Jeśli zainstalowałbym framework w innym folderze, powiedzmy, że framework folderów musi przekierować z powrotem do http://www.example.com/framework/index.php
Chciałbym przekierować każdy folder i plik php z powrotem do index.php, pozostawiając wszystko inne tak, jak jest.
Mój pierwszy problem, jaki napotkałem, polegał na tym, że nigdy nie przekierowywał do właściwego folderu, zawsze do głównego folderu domeny.
Oto, czego próbowałem:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
index.php
czy chcesz przekierować każde żądanie wysłane do tego konkretnego folderuindex.php
?Odpowiedzi:
Twoja reguła przepisywania wygląda prawie dobrze.
Najpierw upewnij się, że
.htaccess
plik znajduje się w katalogu głównym dokumentu (w tym samym miejscuindex.php
), w przeciwnym razie wpłynie to tylko na podfolder, w którym się znajduje (i wszystkie podfoldery w nim - rekurencyjnie).Następnie wprowadź niewielką zmianę w swojej regule, aby wyglądała mniej więcej tak:
W chwili, gdy po prostu dopasowujesz, na
.
którym jest jedna instancja dowolnej postaci, musisz przynajmniej.*
dopasować dowolną liczbę instancji dowolnej postaci.$_GET['path']
Zmienna będzie zawierać strukturę katalogów fałszywe, więc/mvc/module/test
na przykład, które można następnie wykorzystać w index.php w celu określenia kontrolera i działania, które chcesz wykonać.Jeśli chcesz, aby cały shebang został zainstalowany w podkatalogu, na przykład
/mvc/
lub/framework/
najmniej skomplikowanym sposobem, jest nieznaczna zmiana reguły przepisywania, aby wziąć to pod uwagę.I upewnij się, że twój plik znajduje się w
index.php
tym folderze, podczas gdy.htaccess
plik znajduje się w katalogu głównym dokumentu.Alternatywa dla
$_GET['path']
(zaktualizowany luty '18 i styczeń '19)W rzeczywistości nie jest konieczne (ani nawet obecnie) ustawianie ścieżki jako
$_GET
zmiennej, wiele frameworków będzie polegać na$_SERVER['REQUEST_URI']
pobieraniu tych samych informacji - zwykle w celu określenia, którego kontrolera użyć - ale zasada jest dokładnie taka sama.Upraszcza to
RewriteRule
nieco, ponieważ nie musisz tworzyć parametru ścieżki (co oznacza, że oryginał OPRewriteRule
będzie teraz działał):Jednak nadal obowiązuje zasada dotycząca instalacji w podkatalogu, np
Flagi:
NC
= Bez wielkości liter (wielkość liter nie ma znaczenia, nie jest to konieczne, ponieważ we wzorcu nie ma znaków)L
= Ostatnia (przestanie pisać po tym przepisaniu, więc upewnij się, że jest to ostatnia rzecz na twojej liście przeróbek)QSA
= Ciąg zapytania Dołącz, na wypadek gdybyś miał?like=penguins
na końcu coś takiego, co chcesz zachować i przekazać do index.php.źródło
Options +Indexes
i index.php zawarte wDirectoryIndex
ty mógł opuścić off index.php całkowicie i po prostu użyć/?path=$1
Dotyczy to kiedy robi przepisywanie przez .htaccess zamiast w<Directory>
dyrektywie typu httpd-vhosts.conf .$_GET['path']
jeśli dodapath=whatever
do adresu URL.$_GET
więc wymagałoby(.*)
to ... to zabawne, ale RewriteRule, z którego OP korzystał 6 lat temu, wtedy nie działało dla nich - ale z architekturą MVC ewoluował z PHP (jak umieściłem w zaktualizowanym bitu z 18 lutego ), teraz ... chyba wyprzedzili swój czas :)/mvc/
Oczywiście nadal potrzebuje poprawnej ścieżki do katalogu.Aby przekierować wszystko, co nie istnieje
index.php
, możesz również użyćFallBackResource
dyrektywyDziała tak samo, jak w
ErrorDocument
przypadku żądania nieistniejącej ścieżki lub pliku na serwerze, dyrektywa po cichu przekazuje żądanie doindex.php
.Jeśli chcesz przekierować wszystko (
including existant files or folders
) doindex.php
, możesz użyć czegoś takiego:Zauważ, że wzorzec
^((?!index\.php).+)$
pasuje do każdego uri, z wyjątkiemindex.php
tego, że wykluczyliśmy ścieżkę docelową, aby zapobiec nieskończonemu błędowi zapętlenia.źródło
DirectoryIndex index.php
*
zamiast+
we wzorcu, jeśli chcesz również przekierować samą ścieżkę główną.Możesz użyć czegoś takiego:
Spowoduje to przekierowanie każdego zapytania do pliku index.php katalogu głównego. Należy pamiętać, że przekierowuje również zapytania dotyczące istniejących plików, takich jak obrazy, pliki javascript lub arkusze stylów.
źródło
Jest jedna "sztuczka" na ten problem, która pasuje do wszystkich scenariuszy, jest to tak oczywiste rozwiązanie, że będziesz musiał spróbować, aby uwierzyć, że faktycznie działa ... :)
Oto jest ...
Zasadniczo prosisz MOD_REWRITE o przekazanie do
index.php
żądania URI zawsze, gdy plik istnieje ORAZ zawsze, gdy żądany plik nie istnieje !Podczas badania kodu źródłowego MOD-REWRITE, aby zrozumieć, jak to działa, zdałem sobie sprawę, że wszystkie jego sprawdzenia mają miejsce zawsze po weryfikacji, czy plik, do którego się odwołuje, istnieje, czy nie. Dopiero wtedy
RegEx
są przetwarzane. Nawet jeśli Twój identyfikator URI wskazuje folder, Apache wymusi sprawdzenie plików indeksu wymienionych w jego pliku konfiguracyjnym.Opierając się na tym prostym odkryciu, okazało się oczywiste, że prosta weryfikacja pliku wystarczyłaby dla wszystkich możliwych wywołań , o ile dwukrotnie dotkniemy sprawdzania obecności pliku i skierujemy oba wyniki do tego samego punktu końcowego, obejmując 100% możliwości.
WAŻNE: Zauważ, że nie ma znaku „ / ” w
index.php
. Domyślnie MOD_REWRITE użyje folderu, który jest ustawiony jako „folder podstawowy” do przekazywania dalej. Piękno polega na tym, że niekoniecznie musi to być „folder główny” witryny, dzięki czemu to rozwiązanie działalocalhost/
każdego podfolderu, który go zastosujesz.Ostatecznie niektóre inne rozwiązania, które testowałem wcześniej (te, które wydawały się działać dobrze) zepsuły zdolność PHP do „wymagania” pliku poprzez jego ścieżkę względną, co jest kłopotliwe. Bądź ostrożny.
Niektórzy mogą powiedzieć, że jest to nieeleganckie rozwiązanie. Może tak jest, ale jeśli chodzi o testy, w kilku scenariuszach, kilku serwerach, kilku różnych wersjach Apache itp., To rozwiązanie działało w 100% we wszystkich przypadkach!
źródło
FallbackResource index.php
linia działała na komputerze Mac (OS X 10.11), ale nie działała pod Centosem 7.5. Jednak:RewriteRule
powoduje to również przepisanie na przykład lokalizacji plików CSS. Ponieważ potrzebowałem przekierować tylko pliki PHP, zmodyfikowałem regułę naRewriteRule ^(.*)php$ index.php [L,QSA]
. YMMV.RewriteRule ^(.*)\.php$ index.php [L,NE,QSA]
(które nie wymagają warunków do działania). Obecnie jednak stosuję mniej kosztowną regułę:RewriteRule ^.+$ index.php [L,NE,QSA]
którą można łączyć z warunkamiRewriteCond %{REQUEST_FILENAME} !-f
iRewriteCond %{REQUEST_FILENAME} !-d
, a nawetRewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)
być naprawdę specyficzną.Głupia odpowiedź, ale jeśli nie możesz dowiedzieć się, dlaczego nie przekierowuje, sprawdź, czy dla folderu internetowego jest włączona następująca opcja.
AllowOverride All
Umożliwi to uruchomienie htaccess, który musi być uruchomiony! (są alternatywy, ale ich brak spowoduje problemy https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )
źródło
Po wykonaniu czynności nie zapomnij zmienić tagu kotwicy, home
Przykład:
źródło
na wypadek, gdybyś nadal zastanawiał się, jak przekierować wszystkie żądania, jeśli katalog istnieje (dla podstawowych folderów i plików platformy) do programu obsługi indeksu struktury, po kilku próbach błędu / sukcesu właśnie zauważyłem, że wystarczy zmienić RewriteCond w .htaccess plik
powyższy warunek to "not found files" i "not found files", ok, a co jeśli po prostu usunie "not found" (! -d) i zakończy się czymś takim jak poniżej:
U mnie zadziałało jak urok
źródło