Leiten Sie alle mit htaccess zu index.php um

129

Ich schreibe ein einfaches PHP-basiertes MVC-ish Framework. Ich möchte, dass dieses Framework in jedem Verzeichnis installiert werden kann.

Mein PHP-Skript erfasst die Anforderungs-URL und teilt sie in Segmente auf. Es macht Segment 1 zum Controller und Segment 2 zur Aktion. Das geht alles gut, wenn ich das mache:

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

Es wird an die spezifische Modulsteuerung und -methode weitergeleitet. Jetzt habe ich einen Standard-Controller, den Home-Controller, der sich im Ordner home befindet.

Wenn ich jetzt direkt auf diesen Ordner zugreife http://www.example.com/mvc/home/ Es wird ein 403 verboten angezeigt, da dieser Ordner existiert, stattdessen sollte er auch zu http://www.example.com zurückkehren /mvc/index.php

Wenn ich das Framework in einem anderen Ordner installiert hätte, sagen wir, das Ordner-Framework muss zurück zu http://www.example.com/framework/index.php umgeleitet werden

Ich möchte jeden Ordner und jede PHP-Datei zurück in die index.php umleiten und alles andere so lassen, wie es ist.

Mein erstes Problem war, dass es nie in den richtigen Ordner umgeleitet wurde, immer in den Domänenstammordner.

Folgendes habe ich versucht:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
David Ericsson
quelle
Nur um sicherzugehen, dass ich Ihre Frage richtig verstehe: Sie möchten jede Anfrage an das Stammverzeichnis index.php umleiten oder Sie möchten jede Anfrage an diesen bestimmten Ordner umleiten index.php?
Technoh
In dem Ordner, in dem sich die htaccess-Datei befindet, befindet sich das Framework-Stammverzeichnis. In meinem Beispiel zurück zum MVC-Verzeichnis
David Ericsson

Antworten:

258

Ihre Umschreiberegel sieht fast in Ordnung aus.

Stellen Sie zunächst sicher, dass sich Ihre .htaccessDatei im Stammverzeichnis Ihres Dokuments befindet (am selben Ort wie index.php). Andernfalls wirkt sich dies nur auf den Unterordner aus, in dem sie sich befindet (und alle darin enthaltenen Unterordner - rekursiv).

Nehmen Sie als Nächstes eine geringfügige Änderung an Ihrer Regel vor, damit sie ungefähr so ​​aussieht:

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

Im Moment sind Sie passende gerade auf .dem eine Instanz von einem beliebigen Zeichen, müssen Sie zumindest ein .*beliebige Anzahl von Instanzen von einem beliebigen Zeichen übereinstimmen.

Die $_GET['path']Variable enthält beispielsweise die gefälschte Verzeichnisstruktur /mvc/module/test, die Sie dann in index.php verwenden können, um den Controller und die Aktionen zu bestimmen, die Sie ausführen möchten.


Wenn Sie möchten, dass der gesamte Shebang in einem Unterverzeichnis installiert wird, z. B. /mvc/oder /framework/am wenigsten kompliziert, ändern Sie die Umschreiberegel geringfügig, um dies zu berücksichtigen.

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

Stellen Sie sicher, dass Sie index.phpsich in diesem Ordner befinden, während sich die .htaccessDatei im Dokumentstamm befindet.


Alternative zu$_GET['path'] (aktualisiert am 18. Februar und 19. Januar)

Es ist eigentlich nicht notwendig (oder auch nicht üblich), den Pfad als $_GETVariable festzulegen. Viele Frameworks verlassen sich darauf $_SERVER['REQUEST_URI'], dass dieselben Informationen abgerufen werden - normalerweise, um zu bestimmen, welcher Controller verwendet werden soll -, aber das Prinzip ist genau das gleiche.

Dies vereinfacht die RewriteRuleleicht , wie Sie das nicht brauchen , erstellen Pfad Parameter (was bedeutet , dass das Original des OP RewriteRule wird jetzt Arbeit):

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

Es gilt jedoch weiterhin die Regel zur Installation in einem Unterverzeichnis, z

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



Die Flaggen:

NC = Keine Groß- / Kleinschreibung (nicht zwischen Groß- und Kleinschreibung unterscheiden, nicht wirklich erforderlich, da das Muster keine Zeichen enthält)

L = Last (nach diesem Umschreiben wird das Umschreiben beendet, stellen Sie also sicher, dass es das Letzte in Ihrer Liste der Umschreibungen ist.)

QSA= Query String Append, nur für den Fall, dass Sie so etwas wie ?like=penguinsam Ende haben, das Sie behalten und an index.php übergeben möchten.

CD001
quelle
1
es sollte index.php sein? path = $ 1
Jacek Pietal
1
@Prozi nicht , wenn Sie in einem Unterverzeichnis sind und index.php im docroot ist, dann müssen Sie das führende / - mit Options +Indexesund index.php , die in DirectoryIndexSie könnten aufhören index.php ganz und verwenden nur /?path=$1Dies gilt , wenn Das Umschreiben erfolgt über .htaccess und nicht über eine Anweisung vom <Directory>Typ httpd-vhosts.conf .
CD001
Wenn Sie das verwenden und sich auf $ _GET ['path'] verlassen, werden Sie Probleme haben, wenn Sie auf den Nginx-Server
wechseln
3
Netter Post! Es ist erwähnenswert, dass der Benutzer überschreiben kann, $_GET['path']wenn path=whateverer der URL etwas hinzufügt .
Rybo111
1
@Liviuge - stimmt, aber anfangs habe ich den gesamten Pfad durchlaufen, $_GETdamit es erforderlich gewesen wäre (.*)... es ist lustig, aber die RewriteRule, die das OP vor 6 Jahren verwendet hat, hat damals nicht für sie funktioniert - aber so wie es die MVC-Architektur getan hat Entwickelt mit PHP (wie ich im aktualisierten Bit vom 18. Februar eingegeben habe) würde es jetzt ... denke, sie waren ihrer Zeit voraus :) Benötigt /mvc/natürlich immer noch den richtigen Pfad zum Verzeichnis.
CD001
28

Um alles umzuleiten, was nicht existiert, index.phpkönnen Sie auch die FallBackResourceDirektive verwenden

FallbackResource /index.php

ErrorDocumentDies funktioniert genauso, wie wenn Sie einen nicht vorhandenen Pfad oder eine nicht vorhandene Datei auf dem Server anfordern, die Direktive die Anforderung stillschweigend weiterleitet index.php.

Wenn Sie alles ( including existant files or folders) umleiten möchten index.php, können Sie Folgendes verwenden:

RewriteEngine on

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

Beachten Sie, dass das Muster ^((?!index\.php).+)$ mit jedem URI übereinstimmt, außer dass index.phpwir den Zielpfad ausgeschlossen haben, um Endlosschleifenfehler zu vermeiden.

Amit Verma
quelle
Aber Sie können auch verwenden:DirectoryIndex index.php
Shao
1
Verwenden Sie *anstelle von +im Muster, wenn Sie auch den Stammpfad selbst umleiten möchten.
Mir-Ismaili
15

Sie können so etwas verwenden:

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

Dadurch wird jede Abfrage in die index.php des Stammverzeichnisses umgeleitet. Beachten Sie, dass auch Abfragen für vorhandene Dateien wie Bilder, Javascript-Dateien oder Stylesheets umgeleitet werden.

Technoh
quelle
1
Diese Lösung hat bei mir fast funktioniert. Ich bekam immer wieder "AH00124: Anfrage hat das Limit von 10 internen Weiterleitungen überschritten". Ich habe vorher "RewriteRule ^ index \ .php - [L]" hinzugefügt und es funktioniert perfekt!
Fredster
11

Es gibt einen "Trick" für dieses Problem , der für alle Szenarien geeignet ist, eine so offensichtliche Lösung, dass Sie ihn ausprobieren müssen, um zu glauben, dass er tatsächlich funktioniert ... :)

Hier ist es...

<IfModule mod_rewrite.c>

   RewriteEngine On

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

</IfModule>

Grundsätzlich bitten Sie MOD_REWRITE , immer dann an index.phpdie URI-Anforderung weiterzuleiten, wenn eine Datei vorhanden ist UND immer dann, wenn die angeforderte Datei nicht vorhanden ist !

Als ich den Quellcode von MOD-REWRITE untersuchte, um zu verstehen, wie es funktioniert, stellte ich fest, dass alle Überprüfungen immer nach der Überprüfung stattfinden, ob die referenzierte Datei vorhanden ist oder nicht. Erst dann RegExwerden die verarbeitet. Selbst wenn Ihr URI auf einen Ordner verweist, erzwingt Apache die Überprüfung der in der Konfigurationsdatei aufgeführten Indexdateien .

Basierend auf dieser einfachen Entdeckung stellte sich heraus, dass eine einfache Dateiüberprüfung für alle möglichen Aufrufe ausreichen würde , sofern wir zweimal auf die Überprüfung der Dateipräsenz tippen und beide Ergebnisse an denselben Endpunkt weiterleiten, wodurch 100% der Möglichkeiten abgedeckt werden.

WICHTIG: Beachten Sie, dass kein " / " vorhanden ist index.php. Standardmäßig verwendet MOD_REWRITE den Ordner, der als " Basisordner " für die Weiterleitung festgelegt ist. Das Schöne daran ist, dass es nicht unbedingt der "Stammordner" der Site sein muss, damit diese Lösung für localhost/und / oder jeden Unterordner funktioniert, den Sie anwenden.

Letztendlich haben einige andere Lösungen, die ich zuvor getestet habe (diejenigen, die anscheinend gut funktionierten), die PHP-Fähigkeit gebrochen, eine Datei über ihren relativen Pfad zu "benötigen", was ein Mist ist. Achtung.

Einige Leute mögen sagen, dass dies eine unelegante Lösung ist. Es mag tatsächlich sein, aber was Tests betrifft, hat diese Lösung in mehreren Szenarien, mehreren Servern, mehreren verschiedenen Apache-Versionen usw. in allen Fällen zu 100% funktioniert!

Julio Marchi
quelle
Vielen Dank, dies hat mein Problem behoben, bei dem eine FallbackResource index.phpLeitung auf einem Mac (OS X 10.11) funktionierte, jedoch nicht unter Centos 7.5. Allerdings: Dadurch wird beispielsweise RewriteRuleauch der Speicherort von CSS-Dateien neu geschrieben. Da ich nur PHP-Dateien umleiten musste, habe ich die Regel auf geändert RewriteRule ^(.*)php$ index.php [L,QSA]. YMMV.
Laryx Decidua
1
Ich bin froh, dass es geholfen hat. Sie haben Recht, es zielt auf ALLE Dateien ab, da die Frage lautete: " Alle mit htaccess auf index.php umleiten ". Es gibt andere elegantere Möglichkeiten, nur PHP-Dateien umzuleiten, z. B. RewriteRule ^(.*)\.php$ index.php [L,NE,QSA](für deren Funktion keine Bedingungen erforderlich sind). Heutzutage verwende ich jedoch eine kostengünstigere Regel RewriteRule ^.+$ index.php [L,NE,QSA]:, die mit den Bedingungen kombiniert werden kann RewriteCond %{REQUEST_FILENAME} !-fund RewriteCond %{REQUEST_FILENAME} !-dsogar RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)wirklich spezifisch ist.
Julio Marchi
5

Dumme Antwort, aber wenn Sie nicht herausfinden können, warum es nicht umleitet, überprüfen Sie, ob das Folgende für den Webordner aktiviert ist.

AllowOverride All

Auf diese Weise können Sie htaccess ausführen, das ausgeführt werden muss! (Es gibt Alternativen, aber nicht aktiviert Probleme https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )

Antonius
quelle
0

Vergessen Sie danach nicht, Ihr Ankertag zu Hause zu ändern

Beispiel:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>
Collins Benson
quelle
Denken Sie immer daran, das <a> -Tag zu ändern.
Collins Benson
2
Was macht Zuhause" , nachdem Sie Ihr Tag nicht geändert haben ?
Enrico Maria De Angelis
0

Nur für den Fall, dass Sie sich immer noch gefragt haben, wie Sie alle Anforderungen umleiten sollen, entweder wenn das Verzeichnis vorhanden ist (für Kern-Framework-Ordner und -Dateien), an den Framework-Index-Handler, nachdem einige Fehler- / Erfolgsversuche gerade bemerkt haben, dass ich nur die RewriteCond in .htaccess ändern musste Datei

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

Die obige Bedingung besagt "nicht gefundene Dateien" und "nicht gefundene Verzeichnisse", ok, was ist, wenn Sie einfach die Zeile "nicht gefunden" (! -d) entfernen und mit etwas wie dem folgenden enden:

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

Es hat bei mir wie ein Zauber funktioniert

AugustoM
quelle