web-dev-qa-db-fra.com

Tout rediriger vers index.php en utilisant htaccess

J'écris un simple framework MVC-ish basé sur PHP. Je veux que ce framework puisse être installé dans n'importe quel répertoire.

Mon script PHP saisit l'uri de la demande et le scinde en segments. Cela fait du segment 1 le contrôleur et du segment 2 l'action. Tout va bien quand je fais ceci:

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

Il ira au contrôleur de module spécifique et à la méthode. Maintenant, j'ai un contrôleur par défaut, le contrôleur domestique, qui se trouve dans le dossier home.

Maintenant, quand j'accède directement à ce dossier http://www.example.com/mvc/home/ Il affichera un message 403 interdit, car ce dossier existe, mais devrait également revenir à - http://www.example.com/mvc/index.php

Si j'aurais installé le framework dans un autre dossier, disons que le framework de dossiers doit être redirigé vers http://www.example.com/framework/index.php

Je voudrais rediriger tous les dossiers et fichiers php vers index.php, en laissant tout le reste tel quel.

Mon premier problème que j'ai rencontré était qu'il ne redirige jamais vers le bon dossier, toujours vers le dossier racine du domaine.

C'est ce que j'ai essayé:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
104
David Ericsson

Votre règle de réécriture semble presque correcte.

Commencez par vous assurer que votre fichier .htaccess se trouve dans la racine de votre document (au même endroit que index.php), sinon cela n'affectera que le sous-dossier dans lequel il se trouve (et tous les sous-dossiers qu'il contient - récursivement). .

Ensuite, modifiez légèrement votre règle pour qu'elle ressemble à ceci:

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

Pour le moment, vous faites juste correspondre sur . qui est une instance de n'importe quel caractère, il vous faut au moins .* pour correspondre à un nombre quelconque N'importe quel caractère.

La variable $_GET['path'] contiendra la structure de répertoire fictive, par exemple /mvc/module/test, que vous pourrez ensuite utiliser dans index.php pour déterminer le Controller et les actions que vous souhaitez effectuer.


Si vous voulez que Shebang soit installé dans un sous-répertoire, tel que /mvc/ ou /framework/, la méthode la moins compliquée consiste à modifier légèrement la règle de réécriture pour en tenir compte. .

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

Et assurez-vous que votre index.php se trouve dans ce dossier, tandis que le fichier .htaccess se trouve à la racine du document.


Alternative à $_GET['path'] (mis à jour le 18 février et le janvier 19)

Il n'est pas vraiment nécessaire (ni même maintenant) de définir le chemin en tant que variable $_GET, de nombreux cadres s'appuieront sur $_SERVER['REQUEST_URI'] pour récupérer les mêmes informations - normalement pour déterminer lequel Contrôleur à utiliser - mais le principe est exactement le même.

Cela simplifie légèrement la RewriteRule, car vous n'avez pas besoin de créer le paramètre path (ce qui signifie que l'original du OP [RewriteRule) sera maintenant, travaille):

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

Cependant , la règle d'installation dans un sous-répertoire s'applique toujours, par exemple.

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



Les drapeaux:

NC = No Case (non sensible à la casse, pas vraiment nécessaire car il n'y a pas de caractères dans le motif)

L = Last (la réécriture s'arrêtera après cette réécriture, assurez-vous que ce soit la dernière chose dans votre liste de réécritures)

QSA = Chaîne de requête Ajouter, juste au cas où vous auriez quelque chose comme ?like=penguins à la fin que vous voulez conserver et que vous voulez transmettre à index.php.

219
CD001

Pour rediriger tout ce qui n'existe pas vers index.php, vous pouvez également utiliser la directive FallBackResource

FallbackResource /index.php

Cela fonctionne de la même manière que ErrorDocument, lorsque vous demandez un chemin ou un fichier inexistant sur le serveur, la directive prévient en mode silencieux la demande à index.php.

Si vous voulez tout rediriger (including existant files or folders) vers index.php, vous pouvez utiliser quelque chose comme ce qui suit:

RewriteEngine on

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

Notez que le modèle ^((?!index\.php).+)$ correspond à n'importe quel uri sauf index.php, nous avons exclu le chemin de destination pour éviter les erreurs de boucle infinies.

26
starkeen

Vous pouvez utiliser quelque chose comme ceci:

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

Cela redirigera chaque requête vers le fichier index.php du répertoire racine. Notez qu'il redirigera également les requêtes pour les fichiers existants, tels que les images, les fichiers javascript ou les feuilles de style.

15
Technoh

Il y a un "truc" pour ce problème qui convient à tous les scénarios, une solution si évidente qu'il vous faudra l'essayer pour le croire fonctionne réellement. :)

C'est ici...

<IfModule mod_rewrite.c>

   RewriteEngine On

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

</IfModule>

En gros, vous demandez MOD_REWRITE de transférer à index.php la demande d'URI toujours lorsqu'un fichier existe AND toujours lorsque le fichier demandé n'existe pas!

En recherchant le code source de MOD-REWRITE pour comprendre son fonctionnement, je me suis rendu compte que toutes ses vérifications avaient toujours lieu après la vérification, que le fichier référencé existe ou non. Alors seulement les RegEx sont traités. Même lorsque votre URI pointe vers un dossier, Apache impose la vérification des fichiers d'index répertoriés dans son fichier de configuration.

Sur la base de cette découverte simple, il devenait évident qu'une simple validation de fichier suffirait pour tous les appels possibles, dans la mesure où nous appuierons deux fois sur le contrôle de présence du fichier et acheminerons les deux résultats vers le même point final, couvrant ainsi: 100% des possibilités.

IMPORTANT: Notez qu'il n'y a pas de "/" dans index.php. Par défaut, MOD_REWRITE utilisera le dossier défini comme "dossier de base" pour le transfert. L'avantage de cette solution est qu'elle ne doit pas nécessairement être le "dossier racine" du site, ce qui permet à cette solution de fonctionner pour localhost/ et/ou tout sous-dossier auquel vous l'appliquez.

En fin de compte, certaines autres solutions que j'ai testées auparavant (celles qui semblaient bien fonctionner) ont cassé la capacité de PHP de "requérir" un fichier via son chemin relatif, ce qui est décevant. Faites attention.

Certaines personnes peuvent dire que c'est une solution peu élégante. En réalité, cela peut être, mais en ce qui concerne les tests, dans plusieurs scénarios, plusieurs serveurs, différentes versions d'Apache, etc., cette solution a fonctionné à 100% dans tous les cas!

9
Julio Marchi

Réponse idiote, mais si vous ne pouvez pas comprendre pourquoi il ne redirige pas, vérifiez que les options suivantes sont activées pour le dossier Web.

AllowOverride All

Cela vous permettra de lancer htaccess qui doit être lancé! (Il y a des alternatives mais pas sur causera des problèmes https://httpd.Apache.org/docs/2.4/mod/core.html#allowoverride )

4
Antony