Redireccionar todo a index.php usando htaccess

131

Estoy escribiendo un marco MVC-ish simple basado en PHP. Quiero que este marco pueda instalarse en cualquier directorio.

Mi script PHP toma la uri de solicitud y la divide en segmentos. Hace que el segmento 1 sea el controlador y el segmento 2 la acción. Todo va bien cuando hago esto:

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

Irá al controlador y método del módulo específico. Ahora tengo un controlador predeterminado, el controlador de inicio, que está en la carpeta de inicio.

Ahora, cuando accedo a esta carpeta directamente http://www.example.com/mvc/home/ Mostrará un 403 prohibido, porque esta carpeta existe, en su lugar también debería volver a http://www.example.com /mvc/index.php

Si hubiera instalado el marco en una carpeta diferente, digamos que el marco de la carpeta tiene que redirigir de nuevo a http://www.example.com/framework/index.php

Me gustaría redirigir cada carpeta y archivo php de nuevo al index.php, dejando todo lo demás como está.

Mi primer problema que encontré fue que nunca se redirige a la carpeta correcta, siempre a la carpeta raíz del dominio.

Esto es lo que probé:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
David Ericsson
fuente
Solo para asegurarme de que entiendo su pregunta correctamente: ¿desea redirigir cada solicitud a la raíz index.php o desea redirigir cada solicitud realizada a esa carpeta específica index.php ?
Technoh
En la carpeta en la que se encuentra el archivo htaccess, el directorio raíz del framework. En mi ejemplo, de vuelta al directorio mvc
David Ericsson el

Respuestas:

259

Su regla de reescritura se ve casi bien.

Primero asegúrese de que su .htaccessarchivo esté en la raíz del documento (el mismo lugar que index.php) o solo afectará la subcarpeta en la que se encuentra (y cualquier subcarpeta dentro de eso, de forma recursiva).

A continuación, realice un ligero cambio en su regla para que se vea algo así como:

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

En el momento en que solo coincida en .cuál es una instancia de cualquier personaje, necesita al menos .*hacer coincidir cualquier número de instancias de cualquier personaje.

La $_GET['path']variable contendrá la estructura de directorio falsa, /mvc/module/testpor ejemplo, que luego puede usar en index.php para determinar el Controlador y las acciones que desea realizar.


Si desea que todo el asunto se instala en un subdirectorio, como por ejemplo /mvc/, o /framework/la forma menos complicada de hacerlo es cambiar la regla de reescritura ligeramente para tener en cuenta.

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

Y asegúrese de que index.phpestá en esa carpeta mientras el .htaccessarchivo está en la raíz del documento.


Alternativa a$_GET['path'] (actualizado febrero '18 y enero '19)

En realidad no es necesario (ni siquiera común ahora) establecer la ruta como una $_GETvariable, muchos marcos dependerán $_SERVER['REQUEST_URI']para recuperar la misma información, normalmente para determinar qué controlador usar, pero el principio es exactamente el mismo.

Esto simplifica el RewriteRuleligeramente a medida que no es necesario para crear la ruta de parámetros (que significa original de la OP RewriteRule hará ahora el trabajo):

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

Sin embargo , la regla sobre la instalación en un subdirectorio todavía se aplica, p. Ej.

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



Las banderas:

NC = Sin mayúsculas y minúsculas (no distingue entre mayúsculas y minúsculas, no es realmente necesario ya que no hay caracteres en el patrón)

L = Último (dejará de reescribirse después de esta Reescritura, así que asegúrese de que sea lo último en su lista de reescrituras)

QSA= Cadena de consulta Anexar, en caso de que tenga algo como ?like=penguinsen el extremo que desea mantener y pasar a index.php.

CD001
fuente
1
debería ser index.php? path = $ 1
Jacek Pietal
1
@Prozi no si estás en un subdirectorio y index.php está en la raíz de documento, entonces no necesita el principal / - con Options +Indexesy index.php incluido en DirectoryIndexle podría dejar fuera de index.php por completo y sólo usar /?path=$1Esto es cierto cuando haciendo reescribe a través de .htaccess en lugar de en una <Directory>directiva de tipo httpd-vhosts.conf .
CD001
Si usa eso y confía en $ _GET ['ruta'], tendrá problemas en caso de pasar al servidor nginx ...
hasta el
3
¡Buen post! Vale la pena señalar que el usuario puede sobrescribir $_GET['path']si agrega path=whatevera la URL.
rybo111
1
@Liviuge: es cierto, pero inicialmente estaba pasando todo el camino, $_GETasí que habría requerido (.*)... es divertido, pero la RewriteRule que el OP estaba usando hace 6 años no funcionó para ellos entonces, pero con la forma en que la arquitectura MVC tiene evolucionó con PHP (como puse en el bit actualizado del 18 de febrero ) ahora ... supongo que se adelantaron a su tiempo :) Todavía necesita la ruta correcta al /mvc/directorio, por supuesto.
CD001
28

Para redirigir todo lo que no existe index.php, también puede usar la FallBackResourcedirectiva

FallbackResource /index.php

Funciona igual que ErrorDocument, cuando solicita una ruta o archivo inexistente en el servidor, la directiva silenciosamente reenvía la solicitud a index.php.

Si desea redirigir todo ( including existant files or folders) a index.php, puede usar algo como lo siguiente:

RewriteEngine on

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

Tenga en cuenta que el patrón ^((?!index\.php).+)$ coincide con cualquier uri, excepto index.phpque hemos excluido la ruta de destino para evitar un error de bucle infinito.

Amit Verma
fuente
Pero también es posible que desee utilizar:DirectoryIndex index.php
Shao
1
Úselo en *lugar de +en el patrón si también desea redirigir la ruta raíz.
Mir-Ismaili
15

Puedes usar algo como esto:

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

Esto redirigirá cada consulta al index.php del directorio raíz. Tenga en cuenta que también redirigirá las consultas para los archivos que existen, como imágenes, archivos javascript o hojas de estilo.

Technoh
fuente
1
Esta solución casi me funcionó. Seguí recibiendo "AH00124: la solicitud superó el límite de 10 redireccionamientos internos". ¡Agregué "RewriteRule ^ index \ .php - [L]" antes y funciona perfectamente!
Fredster
11

Hay un "truco" para este problema que se adapta a todos los escenarios, una solución tan obvia que tendrá que probarlo para creer que realmente funciona ... :)

Aquí está...

<IfModule mod_rewrite.c>

   RewriteEngine On

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

</IfModule>

Básicamente, le está pidiendo a MOD_REWRITE que reenvíe index.phpla solicitud de URI siempre que exista un archivo ¡ Y siempre que el archivo solicitado no exista !

Al investigar el código fuente de MOD-REWRITE para comprender cómo funciona, me di cuenta de que todas sus comprobaciones siempre ocurren después de la verificación si el archivo al que se hace referencia existe o no. Solo entonces RegExse procesan. Incluso cuando su URI apunta a una carpeta, Apache aplicará la verificación de los archivos de índice que figuran en su archivo de configuración.

Basado en ese simple descubrimiento, resultó obvio que una validación de archivo simple sería suficiente para todas las llamadas posibles , siempre que toquemos dos veces la verificación de presencia del archivo y enrutemos ambos resultados al mismo punto final, cubriendo el 100% de las posibilidades.

IMPORTANTE: Observe que no hay " / " en index.php. Por defecto, MOD_REWRITE usará la carpeta que está configurada como "carpeta base" para el reenvío. Lo bueno de esto es que no necesariamente tiene que ser la "carpeta raíz" del sitio, lo que permite que esta solución funcione para localhost/cualquier subcarpeta que la aplique.

En última instancia, algunas otras soluciones que probé antes (las que parecían estar funcionando bien) rompieron la capacidad de PHP de "requerir" un archivo a través de su ruta relativa, que es un fastidio. Ten cuidado.

Algunas personas pueden decir que esta es una solución poco elegante. Puede ser, en realidad, pero en lo que respecta a las pruebas, en varios escenarios, varios servidores, varias versiones diferentes de Apache, etc., ¡esta solución funcionó al 100% en todos los casos!

Julio Marchi
fuente
Gracias, esto solucionó mi problema por el cual una FallbackResource index.phplínea funcionaba en una Mac (OS X 10.11) pero no funcionaba bajo Centos 7.5. Sin embargo: esto RewriteRuletambién reescribe la ubicación de los archivos CSS, por ejemplo. Como necesitaba redirigir solo archivos PHP, modifiqué la regla RewriteRule ^(.*)php$ index.php [L,QSA]. YMMV.
Laryx Decidua
1
Estoy feliz de que haya ayudado. Tiene razón, apunta a TODOS los archivos porque la pregunta era: " Redirigir todo a index.php usando htaccess ". Hay otras formas más elegantes de redirigir solo archivos PHP, como RewriteRule ^(.*)\.php$ index.php [L,NE,QSA](que no necesita condiciones para funcionar). Hoy en día, sin embargo, uso una regla más económica: RewriteRule ^.+$ index.php [L,NE,QSA]que se puede combinar con las condiciones RewriteCond %{REQUEST_FILENAME} !-fy RewriteCond %{REQUEST_FILENAME} !-d, o incluso con RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)ser realmente específico.
Julio Marchi
5

Respuesta tonta, pero si no puede entender por qué no está redirigiendo, verifique que lo siguiente esté habilitado para la carpeta web.

AllowOverride All

¡Esto le permitirá ejecutar htaccess que debe estar ejecutándose! (existen alternativas pero no activadas causarán problemas https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )

Antonio
fuente
0

Después de hacerlo, no olvide cambiar su etiqueta de anclaje, inicio

Ejemplo:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>
Collins Benson
fuente
Recuerde siempre cambiar la etiqueta <a>.
Collins Benson el
2
¿Qué significa después de hacer el no cambiar su etiqueta, inicio ?
Enrico Maria De Angelis
0

en caso de que aún se pregunte cómo redirigir todas las solicitudes, ya sea si el directorio existe (para las carpetas y los archivos del marco central) al controlador del índice del marco, después de algunos intentos de error / éxito, noté que solo necesitaba cambiar el RewriteCond en el .htaccess expediente

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

la condición anterior indica "archivos no encontrados" y "directorios no encontrados", ok, ¿qué pasa si simplemente elimina la línea "no encontrado" (! -d) y termina con algo como lo siguiente:

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

Funcionó para mí como un encanto

AugustoM
fuente