"Links bonitos" é um tópico frequentemente solicitado, mas raramente é totalmente explicado. O mod_rewrite é uma maneira de criar "links bonitos", mas é complexo e sua sintaxe é muito concisa, difícil de entender, e a documentação pressupõe um certo nível de proficiência em HTTP. Alguém pode explicar em termos simples como "links bonitos" funcionam e como mod_rewrite pode ser usado para criá-los?
Outros nomes comuns, aliases, termos para URLs limpos: URLs RESTful , URLs amigáveis ao usuário, URLs amigáveis ao SEO , slugging e URLs MVC (provavelmente um nome impróprio)
apache
.htaccess
mod-rewrite
friendly-url
deceze
fonte
fonte
reference-mod-rewrite-url-rewriting-explained
é a lesma,/questions/20563772/reference-mod-rewrite-url-rewriting-explained
é a URL bonita..htaccess
emod-rewrite
devem ser atualizadas para incluir um link para essa pergunta, pois abrange muito do que é solicitado regularmente. Pensamentos?Respostas:
Para entender qual mod_rewrite você precisa primeiro entender como um servidor da web funciona. Um servidor da web responde às solicitações HTTP . Uma solicitação HTTP em seu nível mais básico se parece com isso:
Essa é a simples solicitação de um navegador para um servidor da Web que solicita a URL
/foo/bar.html
dele. É importante ressaltar que ele não solicita um arquivo , solicita apenas uma URL arbitrária. A solicitação também pode ser assim:Essa solicitação é igualmente válida para um URL e obviamente não tem nada a ver com arquivos.
O servidor da Web é um aplicativo que atende a uma porta, aceitando solicitações HTTP que entram nessa porta e retornando uma resposta. Um servidor da Web é totalmente livre para responder a qualquer solicitação da maneira que achar melhor / da maneira que você configurou para responder. Esta resposta não é um arquivo, é uma resposta HTTP que pode ou não ter nada a ver com arquivos físicos em qualquer disco. Um servidor web não precisa ser o Apache, existem muitos outros servidores web, todos programas que são executados persistentemente e estão conectados a uma porta que responde a solicitações HTTP. Você pode escrever um você mesmo. Este parágrafo tinha como objetivo separar você de qualquer noção de que os URLs sejam iguais a arquivos diretamente, o que é realmente importante de entender. :)
A configuração padrão da maioria dos servidores da Web é procurar um arquivo que corresponda à URL no disco rígido. Se a raiz do documento do servidor estiver configurada para, por exemplo
/var/www
, ele poderá verificar se o arquivo/var/www/foo/bar.html
existe e servi-lo, se houver. Se as extremidades de arquivo em ".php" que irá chamar o intérprete PHP e , em seguida, retornar o resultado. Toda essa associação é completamente configurável; um arquivo não precisa terminar em ".php" para o servidor Web executá-lo através do interpretador PHP, e a URL não precisa corresponder a nenhum arquivo específico no disco para que algo aconteça.mod_rewrite é uma maneira de reescrever o tratamento de solicitações internas. Quando o servidor da web recebe uma solicitação para a URL
/foo/bar
, você pode reescrevê-la em outra coisa antes que o servidor procure um arquivo no disco para corresponder a ele. Exemplo simples:Esta regra diz que sempre que uma solicitação corresponder a "/ foo / bar", reescreva-a em "/ foo / baz". A solicitação será tratada como se
/foo/baz
tivesse sido solicitada. Isso pode ser usado para vários efeitos, por exemplo:Essa regra corresponde a qualquer coisa (
.*
) e a captura ((..)
), depois a reescreve para acrescentar ".html". Em outras palavras, se/foo/bar
foi o URL solicitado, ele será tratado como se/foo/bar.html
tivesse sido solicitado. Consulte http://regular-expressions.info para obter mais informações sobre correspondência, captura e substituição de expressões regulares.Outra regra frequentemente encontrada é esta:
Novamente, isso corresponde a qualquer coisa e a reescreve no arquivo index.php com a URL solicitada originalmente anexada no
url
parâmetro de consulta. Ou seja, para todos e quaisquer pedidos que chegam, o arquivo index.php é executado e esse arquivo terá acesso ao pedido original$_GET['url']
, para que ele possa fazer o que quiser com ele.Primeiramente, você coloca essas regras de reescrita no arquivo de configuração do servidor da web . O Apache também permite * que você os coloque em um arquivo chamado
.htaccess
dentro da raiz do documento (ou seja, próximo aos arquivos .php).* Se permitido pelo arquivo de configuração principal do Apache; é opcional, mas geralmente ativado.
O que mod_rewrite não faz
mod_rewrite não torna magicamente todos os seus URLs "bonitos". Este é um mal-entendido comum. Se você possui este link no seu site:
não há nada que o mod_rewrite possa fazer para tornar isso bonito. Para fazer deste um link bonito, você deve:
Mude o link para um link bonito:
Use mod_rewrite no servidor para manipular a solicitação para a URL
/my/pretty/link
usando qualquer um dos métodos descritos acima.(Pode-se usar
mod_substitute
em conjunto para transformar páginas HTML de saída e seus links contidos. Embora isso seja geralmente mais esforço do que apenas atualizar seus recursos HTML.)Há muito o que mod_rewrite pode fazer e regras de correspondência muito complexas que você pode criar, incluindo encadear várias reescritas, solicitações de proxy para um serviço ou máquina completamente diferente, retornar códigos de status HTTP específicos como respostas, redirecionar solicitações etc. É muito poderoso e pode ser usado para ótimo se você entender o mecanismo fundamental de solicitação e resposta HTTP. Ele não torna seus links automaticamente bonitos.
Consulte a documentação oficial para todos os sinalizadores e opções possíveis.
fonte
Para expandir a resposta de deceze , eu queria fornecer alguns exemplos e explicações sobre outras funcionalidades do mod_rewrite.
Todos os exemplos abaixo assumem que você já incluiu
RewriteEngine On
no seu.htaccess
arquivo.Reescrever Exemplo
Vamos pegar este exemplo:
A regra é dividida em 4 seções:
RewriteRule
- inicia a regra de reescrita^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
- Isso é chamado de padrão, no entanto, vou me referir a ele como o lado esquerdo da regra - do que você deseja reescreverblog/index.php?id=$1&title=$2
- chamado de substituição, ou lado direito de uma regra de reescrita - no que você deseja reescrever[NC,L,QSA]
são sinalizadores para a regra de reescrita, separados por vírgula, que explicarei mais adianteA reescrita acima permitiria que você vinculasse a algo assim
/blog/1/foo/
e, na verdade, seria carregado/blog/index.php?id=1&title=foo
.Lado esquerdo da regra
^
indica o início do nome da página - para reescrever,example.com/blog/...
mas não paraexample.com/foo/blog/...
(…)
parênteses representa uma expressão regular que podemos capturar como uma variável no lado direito da regra. Neste exemplo:([0-9]+)
- corresponde a uma sequência com no mínimo 1 caractere de comprimento e apenas com valores numéricos (ou seja, de 0 a 9). Isso pode ser referenciado$1
no lado direito da regra-
ou+
(a nota+
é escapada com uma barra invertida, pois, sem escape, isso será executado como uma expressão regular caráter de repetição ). Isso pode ser referenciado$2
no lado direito da regra?
significa que o caractere anterior é opcional, portanto, neste caso, ambos/blog/1/foo/
e/blog/1/foo
reescreveriam no mesmo local$
indica que este é o fim da string que queremos corresponderBandeiras
Essas são as opções adicionadas entre colchetes no final de sua regra de reescrita para especificar determinadas condições. Novamente, existem muitos sinalizadores diferentes que você pode ler na documentação , mas analisarei alguns dos sinalizadores mais comuns:
O sinalizador no case significa que a regra de reescrita não faz distinção entre maiúsculas e minúsculas; portanto, para a regra de exemplo acima, isso significaria que ambos
/blog/1/foo/
e/BLOG/1/foo/
(ou qualquer variação disso) seriam correspondidos.O último sinalizador indica que esta é a última regra que deve ser processada. Isso significa que, se e somente se essa regra corresponder, nenhuma regra adicional será avaliada na execução do processamento de reescrita atual. Se a regra não corresponder, todas as outras regras serão tentadas em ordem, como de costume. Se você não definir o
L
sinalizador, todas as regras a seguir serão aplicadas ao URL reescrito posteriormente.Desde o Apache 2.4, você também pode usar a
[END]
bandeira. Uma regra correspondente terminará completamente o processamento de alias / reescrita. (Enquanto o[L]
sinalizador muitas vezes pode acionar uma segunda rodada, por exemplo, quando reescrever dentro ou fora de subdiretórios.)O sinalizador de acréscimo da cadeia de consulta nos permite passar variáveis extras para o URL especificado, que será adicionado aos parâmetros de obtenção originais. Para o nosso exemplo, isso significa que algo como
/blog/1/foo/?comments=15
carregaria/blog/index.php?id=1&title=foo&comments=15
Essa bandeira não é a que usei no exemplo acima, mas achei que vale a pena mencionar. Isso permite que você especifique um redirecionamento http, com a opção de incluir um código de status (por exemplo
R=301
). Por exemplo, se você quisesse fazer um redirecionamento 301 em / myblog / to / blog /, você simplesmente escreveria uma regra mais ou menos assim:Condições de reescrita
As condições de reescrita tornam as reescritas ainda mais poderosas, permitindo especificar reescritas para situações mais específicas. Você pode ler sobre muitas condições na documentação , mas abordarei alguns exemplos comuns e os explicarei:
Essa é uma prática muito comum, que antecederá seu domínio
www.
(se já não estiver lá) e executará um redirecionamento 301. Por exemplo, carregá-http://example.com/blog/
lo o redirecionaria parahttp://www.example.com/blog/
Isso é um pouco menos comum, mas é um bom exemplo de regra que não é executada se o nome do arquivo for um diretório ou arquivo que existe no servidor.
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
executará apenas a reescrita de arquivos com uma extensão de arquivo jpg, jpeg, gif ou png (sem distinção entre maiúsculas e minúsculas).%{REQUEST_FILENAME} !-f
verificará se o arquivo existe no servidor atual e só executará a reescrita se não existir%{REQUEST_FILENAME} !-d
verificará se o arquivo existe no servidor atual e só executará a reescrita se não existirfonte
Referências
O Stack Overflow possui muitos outros ótimos recursos para começar:
(lembre-se de remover a barra nos
^/
prefixos de padrão para.htaccess
uso).E visões gerais sobre regex para iniciantes, mesmo:
Espaços reservados frequentemente usados
.*
corresponde a qualquer coisa, até mesmo uma string vazia. Você não deseja usar esse padrão em qualquer lugar, mas frequentemente na última regra de fallback.[^/]+
é mais frequentemente usado para segmentos de caminho. Corresponde a qualquer coisa, menos à barra.\d+
corresponde apenas a cadeias numéricas.\w+
corresponde a caracteres alfanuméricos. É basicamente uma abreviação de[A-Za-z0-9_]
.[\w\-]+
para segmentos de caminho no estilo "lesma", usando letras, números, traço-
e_
[\w\-.,]+
adiciona pontos e vírgulas. Prefira um\-
traço escapado nas[…]
charclasses.\.
denota um período literal. Caso contrário,.
fora de[…]
é um espaço reservado para qualquer símbolo.Cada um desses espaços reservados geralmente é colocado entre
(…)
parênteses como grupo de captura. E todo o padrão geralmente nos^………$
marcadores de início e fim. Citar "padrões" é opcional.RewriteRules
Os exemplos a seguir são centrados no PHP e um pouco mais incrementais, mais fáceis de adaptar para casos semelhantes. São apenas resumos, geralmente vinculados a mais variações ou perguntas e respostas detalhadas.
Mapeamento estático
/contact
,/about
Reduzir alguns nomes de página para esquemas de arquivos internos é mais simples:
Identificadores numéricos
/object/123
A introdução de atalhos como
http://example.com/article/531
os scripts PHP existentes também é fácil. O espaço reservado numérico pode ser remapeado apenas para um$_GET
parâmetro:Espaços reservados no estilo lesma
/article/with-some-title-slug
Você pode estender facilmente essa regra para permitir
/article/title-string
espaços reservados:Observe que seu script deve poder (ou ser adaptado) mapear esses títulos de volta para os IDs do banco de dados. Somente o RewriteRules não pode criar ou adivinhar informações do nada.
Lesmas com prefixos numéricos
/readable/123-plus-title
Portanto, você verá frequentemente
/article/529-title-slug
caminhos mistos usados na prática:Agora você pode simplesmente ignorar a passagem de
title=$2
qualquer maneira, porque seu script normalmente depende do ID do banco de dados de qualquer maneira. A-title-slug
decoração de URL se tornou arbitrária.Uniformidade com listas alternativas
/foo/…
/bar/…
/baz/…
Se você tiver regras semelhantes para vários caminhos de página virtual, poderá combiná-las e compactá-las com
|
listas alternativas. E, novamente, apenas reatribua-os aos parâmetros GET internos:Você pode dividi-los em
RewriteRule
s individuais, se isso for muito complexo.Envio de URLs relacionados para diferentes back-end
/date/SWITCH/backend
Um uso mais prático de listas alternativas é o mapeamento de caminhos de solicitação para scripts distintos. Por exemplo, para fornecer URLs uniformes para um aplicativo Web mais antigo e mais novo, com base nas datas:
Isso simplesmente remapeia as postagens de 2009-2011 em um script e todos os outros anos implicitamente em outro manipulador. Observe a regra mais específica que vem primeiro . Cada script pode usar diferentes parâmetros GET.
Outros delimitadores que não sejam apenas
/
barras/user-123-name
Você costuma ver RewriteRules para simular uma estrutura de diretório virtual. Mas você não é forçado a não ser criativo. Você também pode usar
-
hífens para segmentação ou estrutura.Para o
/wiki:section:Page_Name
esquema também comum :Ocasionalmente, é adequado alternar entre
/
-delimitadores e:
ou.
na mesma regra mesmo. Ou tenha duas RewriteRules novamente para mapear variantes em scripts diferentes.À direita opcional
/
barra/dir
=/dir/
Ao optar por caminhos no estilo de diretório, você pode torná-lo acessível com e sem um final /
Agora isso lida com ambos
http://example.com/blog/123
e/blog/123/
. E/?$
é fácil anexar a abordagem a qualquer outra RewriteRule.Segmentos flexíveis para caminhos virtuais
.*/.*/.*/.*
A maioria das regras encontradas mapeará um conjunto restrito de
/…/
segmentos do caminho do recurso para parâmetros GET individuais. Alguns scripts lidam com um número variável de opções, no entanto. O mecanismo regexp do Apache não permite opcionalizar um número arbitrário deles. Mas você pode expandi-lo facilmente para uma regra:Se você precisar de até cinco segmentos de caminho, copie esse esquema em cinco regras. Obviamente, você pode usar um
[^/]+
espaço reservado mais específico para cada um. Aqui, a encomenda não é tão importante quanto nenhuma das duas se sobrepõe. Portanto, ter os caminhos mais usados primeiro é bom.Como alternativa, você pode utilizar os parâmetros da matriz do PHPs via
?p[]=$1&p[]=$2&p[]=3
string de consulta aqui - se o seu script simplesmente os preferir antes da divisão. (Embora seja mais comum usar apenas uma regra geral, e deixar o próprio script expandir os segmentos fora do REQUEST_URI.)Consulte também: Como transformar meus segmentos de caminho da URL em pares de valores-chave da cadeia de consulta?
Segmentos opcionais
prefix/opt?/.*
Uma variação comum é ter prefixos opcionais dentro de uma regra. Isso geralmente faz sentido se você tiver cadeias estáticas ou espaços reservados mais restritos ao redor:
Agora, o padrão mais complexo
(?:/([^/])+)?
simplesmente envolve um grupo que não captura(?:…)
e o torna opcional)?
. O espaço reservado contido([^/]+)
seria o padrão de substituição$2
, mas ficará vazio se não houver/…/
caminho do meio .Capturar o restante
/prefix/123-capture/…/*/…whatever…
Como dito anteriormente, muitas vezes você não deseja padrões de reescrita genéricos demais. No entanto, faz sentido combinar comparações estáticas e específicas com
.*
algumas vezes.Isso opcionalizou todos
/…/…/…
os segmentos de caminho à direita. O que, é claro, exige que o script de manipulação os divida, e a variável extraiu os próprios parâmetros (que é o que as estruturas Web-"MVC" fazem).Trailing file "extensions"
/old/path.HTML
Os URLs realmente não têm extensões de arquivo. É disso que trata toda essa referência (= URLs são localizadores virtuais, não necessariamente uma imagem direta do sistema de arquivos). No entanto, se você já tinha um mapeamento de arquivo 1: 1, pode criar regras mais simples:
Outros usos comuns são remapear
.html
caminhos obsoletos para.php
manipuladores mais novos ou apenas aliasizar nomes de diretório apenas para arquivos individuais (reais / reais).Ping-Pong (redireciona e reescreve em uníssono)
/ugly.html
← →/pretty
Então, em algum momento, você está reescrevendo suas páginas HTML para conter apenas links bonitos, conforme descrito por deceze . Enquanto isso, você ainda receberá solicitações dos caminhos antigos , às vezes até de favoritos. Como solução alternativa , você pode usar os navegadores de pingue-pongue para exibir / estabelecer os novos URLs.
Esse truque comum envolve o envio de um redirecionamento 30x / Location sempre que um URL de entrada segue o esquema de nomeação obsoleto / feio. Os navegadores solicitarão novamente a URL nova / bonita, que depois será reescrita (apenas internamente) no local original ou novo.
Observe como este exemplo usa apenas em
[END]
vez de[L]
alternar com segurança. Para versões mais antigas do Apache 2.2, você pode usar outras soluções alternativas, além de remapear os parâmetros da string de consulta, por exemplo: Redirecionar URL feio para bonito, remapear de volta para o caminho feio, sem loops infinitosEspaços ␣em padrões
/this+that+
Não é tão bonito nas barras de endereço do navegador, mas você pode usar espaços nos URLs. Para reescrever padrões, use
\␣
espaços com barras invertidas ."
Caso contrário, apenas cite todo o padrão ou substituição:Os clientes serializam URLs com
+
ou%20
para espaços. No entanto, em RewriteRules, eles são interpretados com caracteres literais para todos os segmentos de caminho relativos.Duplicatas frequentes:
Catch-all para um script central do despachante / controlador frontal
Geralmente usado por estruturas PHP ou scripts do WebCMS / portal. A divisão do caminho real é tratada no PHP usando
$_SERVER["REQUEST_URI"]
. Portanto, conceitualmente, é praticamente o oposto do tratamento de URL "por mod_rewrite". (Basta usarFallBackResource
.)Remover
www.
do nome do hostObserve que isso não copia uma string de consulta, etc.
Consulte também:
· Reescrita de URL para diferentes protocolos em .htaccess
· O htaccess genérico redireciona www para não www
· .htaccess - como forçar "www". de uma maneira genérica?
Observe que os combos RewriteCond / RewriteRule podem ser mais complexos, com correspondências (
%1
e$1
) interagindo nas duas direções, mesmo:Manual do Apache - introdução mod_rewrite , Copyright 2015 The Apache Software Foundation, AL-2.0
Redirecionar para
HTTPS://
Veja também: https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
"Removendo" a extensão PHP
Consulte também: Removendo a extensão .php com mod_rewrite
Aliasing caminhos .html antigos para scripts .php
Consulte: http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
Reescreva do URL como "/ page" para um script como "/index.php/page"
Veja mod_rewrite, php e o arquivo .htaccess
Redirecionar subdomínio para uma pasta
Consulte Como posso fazer meu htaccess funcionar (subdomínios)?
prevalentes
.htaccess
armadilhasAgora leve isso com um grão de sal. Nem todo conselho pode ser generalizado para todos os contextos. Este é apenas um resumo simples de alguns obstáculos conhecidos e pouco óbvios:
Ativar
mod_rewrite
e.htaccess
Para realmente usar RewriteRules nos arquivos de configuração por diretório, você deve:
Verifique se o seu servidor está
AllowOverride All
ativado . Caso contrário, suas.htaccess
diretivas por diretório serão ignoradas e RewriteRules não funcionará.Obviamente, ter
mod_rewrite
habilitado em suahttpd.conf
seção de módulos.Anexe cada lista de regras com
RewriteEngine On
ainda. Embora o mod_rewrite esteja implicitamente ativo nas seções<VirtualHost>
e<Directory>
, os.htaccess
arquivos por diretório precisam ser convocados individualmente.A barra principal
^/
não correspondeVocê não deve iniciar seus
.htaccess
padrões RewriteRule^/
normalmente:Isso geralmente é visto em tutoriais antigos. E costumava estar correto para as versões antigas do Apache 1.x. Atualmente, os caminhos de solicitação são convenientemente totalmente relativos ao diretório em
.htaccess
RewriteRules. Apenas deixe o líder de/
fora.· Observe que a barra principal ainda está correta nas
<VirtualHost>
seções. É por isso que você costuma vê-lo^/?
opcionalizado por paridade de regras.· Ou ao usar um,
RewriteCond %{REQUEST_URI}
você ainda corresponderia a um líder/
.· Consulte também Webmaster.SE: quando é a barra inicial (/) necessária nos padrões mod_rewrite?
<IfModule *>
invólucros começar!Você provavelmente já viu isso em muitos exemplos:
<VirtualHost>
seções - se é que foi combinado com outra opção de recurso, como ScriptAliasMatch. (Mas ninguém nunca faz isso)..htaccess
conjuntos de regras padrão com muitos projetos de código aberto. Lá, ele é apenas um substituto e mantém os URLs "feios" como padrão.No entanto, você não quer isso normalmente em seus próprios
.htaccess
arquivos.500
erros de HTTP . Em geral, o que ele realiza é agregar seus usuários com404
erros de HTTP . (Não é muito mais fácil de usar se você pensar a respeito.)Não use a
RewriteBase
menos que necessárioMuitos exemplos de copiar e colar contêm uma
RewriteBase /
diretiva. O que passa a ser o padrão implícito de qualquer maneira. Então você realmente não precisa disso. É uma solução alternativa para esquemas sofisticados de reescrita do VirtualHost e caminhos DOCUMENT_ROOT equivocados para alguns hosts compartilhados.Faz sentido usar com aplicativos da web individuais em subdiretórios mais profundos. Pode reduzir os padrões RewriteRule nesses casos. Geralmente, é melhor preferir especificadores de caminho relativo em conjuntos de regras por diretório.
Consulte também Como o RewriteBase funciona em .htaccess
Desativar
MultiViews
quando caminhos virtuais se sobrepõemA reescrita de URL é usada principalmente para oferecer suporte a caminhos de entrada virtuais . Comumente você só tem um roteiro despachante (
index.php
) ou alguns manipuladores individuais (articles.php
,blog.php
,wiki.php
, ...). O último pode colidir com caminhos RewriteRule virtuais semelhantes.Uma solicitação, por
/article/123
exemplo, poderia mapear paraarticle.php
com um/123
PATH_INFO implicitamente. Você teria que guardar suas regras com o lugar-comumRewriteCond
!-f
+!-d
e / ou desativar o suporte PATH_INFO, ou talvez apenas desativarOptions -MultiViews
.O que não quer dizer que você sempre precise . Negociação de conteúdo é apenas um automatismo para recursos virtuais.
Encomendar é importante
Veja Tudo o que você sempre quis saber sobre mod_rewrite, se ainda não o fez. A combinação de várias RewriteRules geralmente leva à interação. Isso não é algo a ser evitado habitualmente por
[L]
bandeira, mas um esquema que você adotará uma vez versado. Você pode re-re-re write caminhos virtuais a partir de uma regra para outro, até que ele atinja um manipulador alvo real.Ainda que você muitas vezes querem ter o maior número de regras específicas (string fixa
/forum/…
padrões, ou espaços reservados mais restritivas[^/.]+
) nas primeiras regras. Regras slurp-all genéricas (.*
) são melhor deixadas para as posteriores . (Uma exceção é umaRewriteCond -f/-d
proteção como bloco principal.)Folhas de estilo e imagens param de funcionar
Quando você introduz estruturas de diretório virtual,
/blog/article/123
isso afeta as referências de recursos relativos em HTML (como<img src=mouse.png>
). Que pode ser resolvido por:href="https://stackoverflow.com/old.html"
ousrc="/logo.png"
<base href="https://stackoverflow.com/index">
à sua<head>
seção HTML . Isso implicitamente religa referências relativas ao que eram antes.Como alternativa, você pode criar RewriteRules adicionais para religar
.css
ou.png
caminhos para seus locais originais. Mas isso é desnecessário ou gera redirecionamentos extras e dificulta o armazenamento em cache.Veja também: CSS, JS e imagens não são exibidas com URL bonito
RewriteConds apenas mascara uma RewriteRule
Um erro de interpretação comum é que um RewriteCond bloqueia várias RewriteRules (porque elas são visualmente organizadas):
O que não ocorre por padrão. Você pode encadeá-los usando a
[S=2]
bandeira. Senão você terá que repeti-los. Embora às vezes você possa criar uma regra primária "invertida" para [END] o processo de reescrita mais cedo.QUERY_STRING isento de RewriteRules
Você não pode corresponder
RewriteRule index.php\?x=y
, porque mod_rewrite se compara apenas aos caminhos relativos por padrão. No entanto, você pode combiná-los separadamente via:Consulte também Como posso combinar variáveis de string de consulta com mod_rewrite?
.htaccess
vs.<VirtualHost>
Se você estiver usando RewriteRules em um arquivo de configuração por diretório, não será necessário se preocupar com o desempenho do regex. O Apache mantém padrões PCRE compilados por mais tempo que um processo PHP com uma estrutura de roteamento comum. Para sites de alto tráfego, você deve considerar a mudança de conjuntos de regras para a configuração do servidor vhost, depois de testados em batalha.
Nesse caso, prefira o
^/?
prefixo do separador de diretório opcionalizado . Isso permite mover RewriteRules livremente entre o PerDir e os arquivos de configuração do servidor.Sempre que algo não funciona
Não se preocupe.
Compare
access.log
eerror.log
Muitas vezes, você pode descobrir como um RewriteRule se comporta mal apenas olhando para você
error.log
eaccess.log
. Correlacione os tempos de acesso para ver qual caminho da solicitação veio originalmente e qual caminho / arquivo o Apache não conseguiu resolver (erro 404/500).Isso não informa qual RewriteRule é o culpado. Mas caminhos finais inacessíveis como esses
/docroot/21-.itle?index.php
podem indicar onde inspecionar mais. Caso contrário, desative as regras até obter alguns caminhos previsíveis.Habilitar o RewriteLog
Consulte os documentos do Apache RewriteLog . Para depuração, você pode habilitá-lo nas seções vhost:
Isso produz um resumo detalhado de como os caminhos de solicitação recebidos são modificados por cada regra:
O que ajuda a restringir regras excessivamente genéricas e contratempos de regex.
Consulte também:
· .htaccess não está funcionando (mod_rewrite)
· Dicas para depuração de regras de reescrita .htaccess
Antes de fazer sua própria pergunta
Como você deve saber, o Stack Overflow é muito adequado para fazer perguntas no mod_rewrite. Torná-los no tópico , incluindo pesquisas e tentativas anteriores (evitar respostas redundantes), demonstrarregex compreensão e:
$_SERVER
ambiente de PHPs , se houver uma incompatibilidade de parâmetro.access.log
eerror.log
para verificar o que as regras existentes resolveram. Melhor ainda, umrewrite.log
resumo.Isso gera respostas mais rápidas e exatas e as torna mais úteis para os outros.
Comente seu
.htaccess
Se você copiar exemplos de algum lugar, lembre-se de incluir a
# comment and origin link
. Embora seja apenas falta de educação omitir a atribuição, muitas vezes prejudica a manutenção mais tarde. Documente qualquer código ou fonte de tutorial. Em particular, enquanto não é monitorado, você deve estar ainda mais interessado em não tratá-los como caixas-pretas mágicas.Não são URLs de "SEO"
Disclaimer: Apenas uma irritação. Você costuma ouvir esquemas de reescrita de URL conhecidos como links "SEO" ou algo assim. Embora isso seja útil para exemplos no Google, é um nome impróprio datado.
Nenhum dos motores de busca modernos são realmente perturbado por
.html
e.php
em segmentos de caminho, ou?id=123
seqüências de consulta para esse assunto. Os motores de busca de idade, tais como AltaVista, fez evitar o rastreamento de sites com caminhos de acesso potencialmente ambígua. Os rastreadores modernos muitas vezes desejam até recursos profundos da Web.Como URLs "bonitas" devem ser usadas conceitualmente para tornar os sites fáceis de usar .
/common/tree/nesting
.No entanto, não sacrifique requisitos exclusivos de conformidade.
Ferramentas
Existem várias ferramentas online para gerar RewriteRules para a maioria dos URLs com parâmetros GET:
Principalmente, apenas
[^/]+
gera espaços reservados genéricos, mas provavelmente é suficiente para sites triviais.fonte
Alternativas ao mod_rewrite
Muitos esquemas básicos de URL virtual podem ser alcançados sem o uso de RewriteRules. O Apache permite que scripts PHP sejam chamados sem
.php
extensão e com umPATH_INFO
argumento virtual .Use o PATH_INFO , Luke
Atualmente,
AcceptPathInfo On
muitas vezes é ativado por padrão. O que basicamente permite que.php
outros URLs de recursos carreguem um argumento virtual:Agora isso
/virtual/path
aparece no PHP como$_SERVER["PATH_INFO"]
onde você pode lidar com qualquer argumento extra da maneira que desejar.Isto não é tão conveniente como tendo Apache segmentos de caminho de entrada separada para
$1
,$2
,$3
e passá-los como distintos$_GET
variáveis para PHP. É apenas emular "URLs bonitas" com menos esforço de configuração.Ative o MultiViews para ocultar o
.php
extensãoA opção mais simples de evitar também
.php
"extensões de arquivo" em URLs é habilitar:Isso faz com que o Apache selecione
article.php
solicitações HTTP/article
devido ao nome de base correspondente. E isso funciona bem em conjunto com o recurso PATH_INFO acima mencionado. Então você pode simplesmente usar URLs comohttp://example.com/article/virtual/title
. O que faz sentido se você tiver um aplicativo Web tradicional com vários pontos / scripts de chamada PHP.Observe que o MultiViews tem um propósito diferente / mais amplo. Ele incorre em uma penalidade de desempenho muito menor , porque o Apache sempre procura outros arquivos com nomes de base correspondentes. É realmente significou para Content-negociação , de modo browser recebem a melhor alternativa entre os recursos disponíveis (como
article.en.php
,article.fr.php
,article.jp.mp4
).SetType ou SetHandler para
.php
scripts sem extensãoUma abordagem mais direcionada para evitar carregar
.php
sufixos em URLs é configurar o manipulador PHP para outros esquemas de arquivos. A opção mais simples é substituir o tipo MIME / manipulador padrão via.htaccess
:Dessa forma, você pode renomear seu
article.php
script para apenasarticle
(sem extensão), mas ainda assim processá-lo como script PHP.Agora isso pode ter implicações de segurança e desempenho, porque todos os arquivos sem extensão seriam canalizados através do PHP agora. Portanto, você pode definir alternativamente esse comportamento apenas para arquivos individuais:
Isso depende um pouco da configuração do servidor e do PHP SAPI usado. Alternativas comuns incluem
ForceType application/x-httpd-php
ouAddHandler php5-script
.Outros esquemas de reescrita do Apache
Entre suas muitas opções, o Apache fornece
mod_alias
recursos - que às vezes funcionam tão bem quantomod_rewrite
o RewriteRules. Observe que a maioria deles deve ser configurada em uma<VirtualHost>
seção, mas não nos.htaccess
arquivos de configuração por diretório .ScriptAliasMatch
é principalmente para scripts CGI, mas também deve funcionar para PHP. Permite regexps como qualquer outroRewriteRule
. Na verdade, talvez seja a opção mais robusta para configurar um controlador frontal abrangente.E uma planície também
Alias
ajuda com alguns esquemas simples de reescrita.Mesmo uma
ErrorDocument
diretiva simples pode ser usada para permitir que um script PHP manipule caminhos virtuais. Observe que essa é uma solução alternativa, no entanto, proíbe qualquer coisa, exceto solicitações GET, e inunda o error.log por definição.Veja http://httpd.apache.org/docs/2.2/urlmapping.html para obter mais dicas.
fonte