Redirecione tudo para index.php usando htaccess

131

Estou escrevendo uma estrutura MVC-ish simples baseada em PHP. Eu quero que essa estrutura possa ser instalada em qualquer diretório.

Meu script PHP pega o uri da solicitação e o divide em segmentos. Torna o segmento 1 o controlador e o segmento 2 a ação. Tudo vai bem quando eu faço isso:

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

Irá para o controlador e método específico do módulo. Agora eu tenho um controlador padrão, o controlador doméstico, que está na pasta home.

Agora, quando eu acessar essa pasta diretamente http://www.example.com/mvc/home/ Ele exibirá 403 proibido, porque essa pasta existe, mas também deve voltar para http://www.example.com /mvc/index.php

Se eu tivesse instalado a estrutura em uma pasta diferente, digamos que a estrutura de pastas precise redirecionar para http://www.example.com/framework/index.php

Gostaria de redirecionar todas as pastas e arquivos php de volta para o index.php, deixando todo o resto do jeito que está.

Meu primeiro problema que encontrei foi que ele nunca redireciona para a pasta correta, sempre para a pasta raiz do domínio.

Isto é o que eu tentei:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
David Ericsson
fonte
Apenas para ter certeza de que entendi sua pergunta corretamente: você deseja redirecionar todas as solicitações para a raiz index.php ou redirecionar todas as solicitações feitas para essa pasta específica index.php ?
Technoh 23/08/13
Para a pasta em que o arquivo htaccess está, o diretório raiz da estrutura. No meu exemplo volta para o diretório MVC
David Ericsson

Respostas:

259

Sua regra de reescrita parece quase correta.

Primeiro, verifique se o seu .htaccessarquivo está na raiz do documento (no mesmo local que index.php) ou afetará apenas a subpasta em que está (e quaisquer subpastas dentro dela - recursivamente).

Em seguida, faça uma pequena alteração na sua regra, para que ela se pareça com:

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

No momento em que você está apenas correspondendo à .qual é uma instância de qualquer caractere, você precisa pelo menos .*corresponder a qualquer número de instâncias de qualquer caractere.

A $_GET['path']variável conterá a estrutura de diretório falsa, portanto, /mvc/module/testpor exemplo, que você pode usar no index.php para determinar o controlador e as ações que deseja executar.


Se você quiser a coisa toda instalado em um sub-diretório, como /mvc/ou /framework/a maneira menos complicada para fazer isso é mudar a regra de reescrita ligeiramente para levar isso em conta.

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

E verifique se você index.phpestá nessa pasta enquanto o .htaccessarquivo está na raiz do documento.


Alternativa para$_GET['path'] (atualizado em fevereiro de 18 e janeiro de 19)

Na verdade, não é necessário (nem mesmo comum agora) definir o caminho como uma $_GETvariável; muitas estruturas dependerão $_SERVER['REQUEST_URI']para recuperar as mesmas informações - normalmente para determinar qual Controlador usar - mas o princípio é exatamente o mesmo.

Isso simplificar o RewriteRulepouco que você não precisa criar o caminho parâmetro (o que significa original do OP RewriteRule será agora trabalho):

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

No entanto , a regra sobre a instalação em um subdiretório ainda se aplica, por exemplo,

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



As bandeiras:

NC = Sem maiúsculas e minúsculas (sem distinção entre maiúsculas e minúsculas, não é realmente necessário, pois não há caracteres no padrão)

L = Último (ele será interrompido após a reescrita, verifique se é a última coisa na sua lista de reescritas)

QSA= String de consulta Anexar, caso você tenha algo parecido ?like=penguinscom o final que deseja manter e passar para index.php.

CD001
fonte
1
deve ser index.php? path = $ 1
Jacek Pietal
1
@Prozi, não se você estiver em um subdiretório e o index.php estiver no docroot, você precisará do / / with Options +Indexese index.php incluído, DirectoryIndexvocê pode deixar o index.php completamente e apenas usar /?path=$1Isso é válido quando reescrever através de .htaccess, em vez de em uma <Directory>diretiva de tipo httpd-vhosts.conf .
CD001
Se você usar isso e contar com $ _GET [ 'caminho'] você estará em apuros no caso de se mudar para servidor nginx ...
Barell
3
Bela postagem! Vale a pena notar que o usuário pode sobrescrever $_GET['path']se adicionar path=whateverao URL.
precisa saber é o seguinte
1
@Liviuge - verdade, mas inicialmente eu estava passando o caminho inteiro para $_GETisso seria necessário (.*)... é engraçado, mas o RewriteRule que o OP estava usando há 6 anos não funcionou para eles na época - mas com a arquitetura MVC evoluiu com PHP (como eu coloquei no Atualizado em 18 de fevereiro ) agora ... acho que eles estavam à frente de seu tempo :) Ainda precisa do caminho correto para o /mvc/diretório, é claro.
CD001 28/01/19
28

Para redirecionar tudo o que não existe index.php, você também pode usar a FallBackResourcediretiva

FallbackResource /index.php

Funciona da mesma maneira que ErrorDocument, quando você solicita um caminho ou arquivo inexistente no servidor, a diretiva define silenciosamente a solicitação index.php.

Se você deseja redirecionar tudo ( including existant files or folders) para index.php, pode usar algo como o seguinte:

RewriteEngine on

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

Observe que o padrão ^((?!index\.php).+)$ corresponde a qualquer uri, exceto index.phpque excluímos o caminho de destino para evitar erros de loop infinito.

Amit Verma
fonte
Mas você também pode querer usar:DirectoryIndex index.php
Shao
1
Use em *vez de +no padrão se desejar redirecionar o próprio caminho raiz também.
Mir-Ismaili
15

Você pode usar algo como isto:

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

Isso redirecionará todas as consultas para o index.php do diretório raiz. Observe que ele também redirecionará as consultas para arquivos existentes, como imagens, arquivos javascript ou folhas de estilo.

Technoh
fonte
1
Essa solução quase funcionou para mim. Continuei recebendo "AH00124: a solicitação excedeu o limite de 10 redirecionamentos internos". Eu adicionei "RewriteRule ^ index \ .php - [L]" antes e funciona perfeitamente!
Fredster #
11

Há um "truque" para esse problema que se adapta a todos os cenários, uma solução tão óbvia que você terá que tentar acreditar que realmente funciona ... :)

Aqui está...

<IfModule mod_rewrite.c>

   RewriteEngine On

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

</IfModule>

Basicamente, você está pedindo ao MOD_REWRITE para encaminhar para index.phpa solicitação de URI sempre que um arquivo existe E sempre que o arquivo solicitado não existe !

Ao investigar o código-fonte do MOD-REWRITE para entender como ele funciona, percebi que todas as suas verificações sempre acontecem após a verificação, se o arquivo referenciado existe ou não. Somente então os RegExsão processados. Mesmo quando o seu URI apontar para uma pasta, o Apache aplicará a verificação dos arquivos de índice listados em seu arquivo de configuração.

Com base nessa descoberta simples, tornou-se óbvio que uma validação simples de arquivo seria suficiente para todas as chamadas possíveis , desde que toque duas vezes na verificação de presença de arquivo e roteie os dois resultados para o mesmo ponto final, cobrindo 100% das possibilidades.

IMPORTANTE: Observe que não há " / " em index.php. Por padrão, MOD_REWRITE usará a pasta que está definida como "pasta base" para o encaminhamento. A vantagem disso é que ele não precisa necessariamente ser a "pasta raiz" do site, permitindo que esta solução funcione para localhost/e / ou para qualquer subpasta aplicada.

Por fim, algumas outras soluções que eu testei antes (aquelas que pareciam estar funcionando bem) quebraram a capacidade do PHP de "exigir" um arquivo por seu caminho relativo, o que é uma chatice. Seja cuidadoso.

Algumas pessoas podem dizer que esta é uma solução deselegante. Pode ser, na verdade, mas quanto aos testes, em vários cenários, vários servidores, várias versões diferentes do Apache, etc., essa solução funcionou 100% em todos os casos!

Julio Marchi
fonte
Obrigado, isso corrigiu meu problema, pelo qual uma FallbackResource index.phplinha funcionava em um Mac (OS X 10.11), mas não no Centos 7.5. No entanto: isso RewriteRuletambém reescreve a localização dos arquivos CSS, por exemplo. Como eu precisava redirecionar apenas arquivos PHP, modifiquei a regra para RewriteRule ^(.*)php$ index.php [L,QSA]. YMMV.
Laryx Decidua
1
Estou feliz que ajudou. Você está certo, ele tem como alvo TODOS os arquivos porque a pergunta era: " Redirecione tudo para index.php usando htaccess ". Existem outras maneiras mais elegantes de redirecionar apenas arquivos PHP, como RewriteRule ^(.*)\.php$ index.php [L,NE,QSA](que não precisa de condições para funcionar). Hoje em dia, porém, uso uma regra mais barata:, RewriteRule ^.+$ index.php [L,NE,QSA]que pode ser combinada com as condições RewriteCond %{REQUEST_FILENAME} !-fe RewriteCond %{REQUEST_FILENAME} !-d, ou até mesmo, RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)para ser verdadeiramente específica.
Julio Marchi
5

Resposta tola, mas se você não consegue descobrir por que não está redirecionando, verifique se o seguinte está ativado para a pasta da web.

AllowOverride All

Isso permitirá que você execute o htaccess, que deve estar em execução! (existem alternativas, mas não ativadas, causarão problemas https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride )

Antony
fonte
0

Depois de fazer o procedimento, não esqueça de alterar sua âncora, página inicial

Exemplo:

.htacces file
RewriteEngine On

RewriteRule ^about/$ /about.php

PHP file:
<a href="about/"> about</a>
Collins Benson
fonte
Lembre-se sempre de alterar a tag <a>.
Collins Benson
2
O que significa Depois de fazer o não para alterar sua tag, home significa?
Enrico Maria De Angelis
0

caso você ainda esteja se perguntando como redirecionar todas as solicitações, caso o diretório exista (para pastas e arquivos principais da estrutura) para o manipulador de índice da estrutura, após algumas tentativas de erro / sucesso, observei que eu só precisava alterar o RewriteCond no .htaccess Arquivo

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

a condição acima indica "arquivos não encontrados" e "diretórios não encontrados", ok, e se apenas remover a linha "não encontrada" (! -d) e terminar com algo como o abaixo:

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

Funcionou para mim como um encanto

AugustoM
fonte