Url mudando com htaccess

Oct 20 2020

Tenho uma apresentação na web com alguns endereços de URL típicos. Agora preciso adicionar um reescrito para uma linguagem diferente, exemplos:

domain/club -> do not change
domain/club/path -> do not change
domain/club/path?search=somethingelse -> do not change
domain/en/club -> domain/club?lang=en
domain/en/club/path -> domain/club/path?lang=en
domain/en/club/path?search=something -> domain/club/path?search=something&lang=endomain

Minha ideia era dividi-lo em grupos domínio / idioma / clube / caminho? Pesquisar = algo e depois escrever

RewriteRule \/(?<language>[a-zA-Z]{2})\/club\/?(?<path>.*)\?(?<search>.*)   /club/$1?search=$2&lang=$3

mas isso não considerará strings sem ?. Também não sei resolver a diferença com dois casos ?lang=e &lang=. Não encontrei nada online.

Estou fazendo isso no framework PHP existente (não em qualquer um dos padrões) e, portanto, tenho que fazer dessa forma (entenda com esses urls específicos).

Respostas

3 MrWhite Oct 20 2020 at 00:36

Parece que você está tornando isso mais complexo do que realmente é. A menos que você precise ser específico sobre a correspondência de "clube", parece que você só precisa remover o primeiro segmento de caminho quando se parece com um código de idioma de duas letras e movê-lo para o langparâmetro de URL na string de consulta.

Para isso, você pode fazer o seguinte, próximo ao topo do seu .htaccessarquivo:

RewriteRule ^([a-z]{2})/(.+) $2?lang=$1 [QSA,L]

Uma solicitação de /en/clubserá reescrita para /club?lang=ene /en/club/path?search=somethingpara /club/path?lang=en&search=something(observe que o langparâmetro de URL é o primeiro).

Explicação:

  • O RewriteRule padrão corresponde apenas ao caminho do URL, não à string de consulta. O caminho da URL que corresponde também não tem um prefixo de barra.
  • ([a-z]{2})- corresponde ao código de idioma de 2 letras (minúsculas). (Embora em sua regex, você tenha permitido letras maiúsculas também?) Este é um subpadrão de captura, portanto, é naturalmente armazenado na (primeira) referência anterior $1.
  • O (.+)corresponde a tudo no caminho de URL que segue o segmento de caminho do código de idioma (e barra). Observe que isso corresponde a algo , não a nada . Por isso não vai ser bem sucedido para um pedido para /en/apenas /en/<something>. (Se isso precisar ser bem-sucedido /en/ apenas também, altere este subpadrão para (.*).) Isso também é capturado e armazenado na (segunda) referência anterior $2. por exemplo. Solicitar /en/club/pathe $2reter club/path.
  • O QSAsinalizador anexa qualquer string de consulta que possa estar presente na solicitação inicial e lida com a "fusão" com qualquer string de consulta na string de substituição . por exemplo. search=something. No entanto, uma pequena diferença com o seu exemplo é que o langparâmetro do URL será o primeiro , não o último - embora isso não deva ser um problema.

No entanto, se isso funciona ou não, ainda depende de como sua "estrutura PHP" roteia URLs. Por exemplo, se for como o WordPress e olhar para a $_SERVER['REQUEST_URI']superglobal do PHP, então ainda verá o caminho da URL antes da reescrita.

Você provavelmente tem outras reescritas depois disso?


RewriteRule \/(?<language>[a-zA-Z]{2})\/club\/?(?<path>.*)\?(?<search>.*) /club/$1?search=$2&lang=$3

mas isso não considerará strings sem ?. Também não sei resolver a diferença com dois casos ?lang=e &lang=. Não encontrei nada online.

Existem vários problemas aqui:

  • O regex não está ancorado no início do caminho do URL, por isso corresponde /<anything>/en/etc.
  • Conforme observado acima, o caminho de URL correspondente ao RewriteRule padrão não começa com uma barra.
  • "isso não considerará strings sem ?" - o URL correspondente ao RewriteRule padrão é apenas o caminho do URL. Isso não inclui a string de consulta. Portanto, tentar corresponder à string de consulta aqui simplesmente falhará. (Se você precisar corresponder à string de consulta, precisará de uma RewriteConddiretiva adicional e corresponder à QUERY_STRINGvariável do servidor.)
  • Não é um erro, mas não há necessidade de barras invertidas de escape no regex, já que a barra não tem nenhum significado especial aqui ( espaços são delimitadores de regex / argumento em arquivos de configuração do Apache). Conforme observado, isso não é estritamente um erro, assim como você pode fazer o escape da maioria dos caracteres com barra invertida, mas complica o regex e torna mais difícil de ler.
  • Você está usando grupos capturados por nome (com suporte no Apache 2.4.8+), mas está usando referências numéricas na string de substituição . Você não pode usar os dois. (É mais fácil ficar com referências numéricas da IMO.)
  • As referências anteriores na string de substituição parecem estar na ordem errada. $1é o código do idioma. por exemplo. deveria ser mais parecido (embora ainda não esteja correto)./club/$2?search=$3&lang=$1
  • "como resolver a diferença com dois casos ?lang=e &lang=" - O QSAsinalizador (Query String Append) faz isso para você. Exceto que a string de consulta é anexada , não prefixada .