Eu lutei com o mesmo problema e pelo mesmo motivo. Eu estou tentando fazer um aplicativo da web independente do local onde ele está instalado, sem recorrer a um script de configuração ou intervenção manual do usuário. Basta soltar o aplicativo em algum lugar e deixar que ele faça o que quiser.
E parece que há uma solução afinal, pelo menos para o Apache 2. Leva quatro linhas. Explicar o pensamento por trás disso leva mais de quatro linhas;)
Tl; dr tente isto:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1#%{REQUEST_URI} ([^#]*)#(.*?)$
RewriteRule ^(.*)$ %2index.php [QSA,L]
Aqui está o como e porquê
-
Não podemos configurar o RewriteBase dinamicamente, por isso, definimos de uma vez por todas o URL raiz do servidor: RewriteBase /
. Isso fornece consistência, mas também significa que temos que estabelecer o caminho da url para o diretório atual e prefixá-lo com a URL reescrita.
-
Em qual diretório estamos? Vamos supor que REQUEST_URI
de / alguma / caminho / raiz de aplicativo / virtual / material. Nosso htaccess está na raiz do aplicativo. Se pegarmos a parte virtual - virtual / material - e removê-la do REQUEST_URI
, ficamos com o caminho-url para o nosso diretório de aplicativos.
-
Capturar a peça virtual é simples e pode acontecer na própria regra de reescrita. RewriteRule ^(.*)$ ...
torna disponível na variável $1
.
-
Agora fazemos nossa pequena operação de string e removemos a parte virtual do URI da solicitação. Nós não temos comandos de string para isso, mas o RewriteCond pode combinar strings e capturar substrings. Então, adicionaremos um RewriteCond com o único propósito de extrair o caminho-url para o diretório atual. Fora isso, a "condição" deve ficar fora do nosso caminho e ser sempre verdadeira.
-
Podemos usar a variável $1
do RewriteRule no RewriteCond porque o mod_rewrite realmente processa um conjunto de regras de trás para frente. Começa com o padrão na própria regra e, se corresponder, passa a verificar as condições. Então a variável está disponível até então.
-
Enquanto a string de teste no RewriteCond pode usar a variável, a condição real regex não pode. Dentro da condição, só podemos usar referências internas. Então, primeiro, montamos uma string de teste "[virtual part] [some separator] [request uri]". O caractere "#" é um bom separador porque não aparece no URL. Em seguida, combinamos com uma condição de
([^#]*) - anything up to the separator, captures the virtual part
# - the separator
(.*?) - anything in the request uri up to what we've captured in group one,
grabs the current directory url-path
$ - group one again, ie the virtual part of the request uri
Então aqui está a condição completa: RewriteCond $1#%{REQUEST_URI} ([^#]*)#(.*?)$
.
-
O segundo grupo capturado no regex RewriteCond é a nossa localização. Precisamos apenas prefixar o URL reescrito com uma referência %2
. Isso nos deixa com RewriteRule ^(.*)$ %2index.php [QSA,L]
. Voilà.
Ainda não fiz testes extensivos, mas estabeleci que funciona com hosts virtuais comuns, bem como hospedagem virtual em massa (usando o VirtualDocumentRoot). Por implicação, outros locais com alias também devem ser bons.
Apache 1.3
O Apache 1.3 ainda está por aí, infelizmente, e vai sufocar no padrão RewriteCond. O Apache 1.3 não suporta o modificador ungreedy (o '?' Em (.*?)
).
Mas para o Apache 2, isso deve funcionar. Eu definitivamente aprecio qualquer feedback, especialmente se ele falhar em seu ambiente.
Edit: Acabei de postar um artigo mais abrangente sobre o assunto em meu blog (" Usando mod_rewrite em. htaccess arquivos sem saber o RewriteBase "). Veja lá para mais detalhes.