Como reordenar parâmetros de URL / string de consulta usando Apache htaccess?
Tenho categorias de comércio eletrônico com navegação facetada (filtragem). A filtragem pode gerar milhares de URLs (úteis). Eu gostaria de reduzir o nr. de URLs possíveis, mostrando determinado conteúdo sempre no mesmo URL com a mesma ordem de parâmetro da string de consulta.
Do ponto de vista do SEO, eu poderia usar a tag canônica para eliminar logicamente URLs duplicados, mas do ponto de vista do desempenho seria muito melhor resolvê-lo com RewriteRules.
URLs de exemplo com o mesmo conteúdo, mas em ordem de parâmetros diferente:
https://example.com/category/subcategory/?filter_manuf=grohe&filter_style=design&filter_family=bauedge&filter_warranty=5yhttps://example.com/category/subcategory/?filter_style=design&filter_manuf=grohe&filter_warranty=5y&filter_family=bauedge
Esses URLs devem ser redirecionados para um URL no qual os parâmetros de consulta aparecem sempre na mesma ordem. por exemplo:
https://example.com/category/subcategory/?filter_manuf=grohe&filter_family=bauedge&filter_style=design&filter_warranty=5y
Observe que:
- Eu tenho mais de 10 critérios de filtragem (parâmetros de consulta)
- A ordem dos parâmetros muda de acordo com a ordem de seleção do filtro do usuário. Eles podem aparecer em qualquer ordem.
- Apenas os parâmetros usados aparecem no URL. Algumas páginas têm um ou dois parâmetros em seu URL, algumas têm até dez ou mais.
Você tem ideia de como isso pode ser alcançado?
Encontrei algo promissor nesta pergunta, mas não consigo fazer funcionar:
RewriteCond para corresponder aos parâmetros da string de consulta em qualquer ordem
Respostas
mas do ponto de vista do desempenho, seria muito melhor resolvê-lo com RewriteRules.
Do ponto de vista do desempenho , seria muito melhor resolver isso em seu aplicativo, não em .htaccess/ mod_rewrite (ou seja, RewriteRules). Você deseja estar sempre vinculado corretamente ao URL canônico.
Você certamente não deseja redirecionar externamente o usuário à medida que ele aplica filtros para "corrigir" a ordem dos parâmetros de URL. Os parâmetros de URL devem ser aplicados da maneira "correta" para começar pelo seu aplicativo.
A única vez em que seria benéfico "redirecionar" o usuário é se ele seguir um link não canônico de terceiros (de outro site ou mecanismo de pesquisa) e você precisar resolver possíveis problemas de SEO. Mas, mesmo assim, o código para corrigir a ordem dos parâmetros de URL deve ser muito mais simples (e mais fácil de manter) se implementado como parte da lógica do seu aplicativo, não .htaccess. O código para fazer isso .htaccessé comparativamente mais "complexo" (leia-se: confuso, potencialmente mais difícil de manter, mais sujeito a erros, etc.)
No entanto, é um problema interessante e pode haver uma ocasião em que seja preferível (ou necessário) codificar isso .htaccess(ou na configuração do servidor Apache) quando você não puder fazer isso facilmente em seu aplicativo.
Solução usando mod_rewrite em .htaccess(ou configuração do servidor)
(No entanto, observe os comentários acima - isso pode não ser o que você deveria fazer.)
Esta é uma solução razoavelmente genérica que funciona em .htaccess(ou configuração de servidor). Como está, funciona em qualquer caminho de URL. Para fazê-lo funcionar em um único caminho de URL (por exemplo /category/subcategory/, como declarado na pergunta), modifique o padrão na RewriteRulediretiva final . Por exemplo:
RewriteRule ^category/subcategory/$ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]
Ou você pode escrever uma exceção na parte superior para ignorar essas regras para determinados URLs se precisar aplicá-la a um grupo de URLs e não a outros. Isso pode ser mais ideal, pois evita qualquer processamento desnecessário da string de consulta.
Este bloco de código precisaria chegar perto do topo do seu .htaccessarquivo. (O pedido é importante.)
Este código tem o "benefício" adicional de também "higienizar" a string de consulta removendo quaisquer parâmetros de URL que não estejam definidos (na parte superior do script).
Uma vez que não é trivial determinar "simplesmente" se os parâmetros de URL originais já estão na ordem correta, o script passa pelo processo de construção de uma nova string de consulta com os parâmetros de URL na ordem correta e, em seguida, compara isso à consulta original string para determinar se um redirecionamento é necessário.
Critério:
- Até 10 parâmetros de URL
- Qualquer número de parâmetros de URL pode aparecer em qualquer ordem
- Parâmetros de URL vazios não devem ser incluídos
- Os parâmetros de URL diferenciam maiúsculas de minúsculas
- Funciona para qualquer caminho de URL
- Nomes de parâmetros de URL corresponder ao regex
[\w-]+(ie.a-z,A-Z,0-9,_E-) - Os valores de parâmetro de URL não podem conter
@(a menos que seja codificado por URL) @@@não pode aparecer em qualquer lugar na string de consulta
Você simplesmente precisa definir os nomes dos parâmetros de URL na parte superior do script, na ordem que deseja. Estes são mantidos em variáveis de ambiente VAR_NAME_01, VAR_NAME_02etc. O restante do script deve funcionar inalterada a menos que:
- você precisa adicionar mais parâmetros de URL
- OU, altere o caractere usado internamente para delimitar seções na correspondência de padrão (atualmente "
@"). - OU, limite o código a um caminho de URL específico.
Roteiro:
# Define the "name" of each URL parameter
# The numeric order determines the order of the resulting URL parameter list.
# Comment out any URL parameters that are not required.
SetEnvIf ^ ^ VAR_NAME_01=one
SetEnvIf ^ ^ VAR_NAME_02=two
SetEnvIf ^ ^ VAR_NAME_03=three
SetEnvIf ^ ^ VAR_NAME_04=four
SetEnvIf ^ ^ VAR_NAME_05=five
SetEnvIf ^ ^ VAR_NAME_06=six
SetEnvIf ^ ^ VAR_NAME_07=seven
SetEnvIf ^ ^ VAR_NAME_08=eight
SetEnvIf ^ ^ VAR_NAME_09=nine
SetEnvIf ^ ^ VAR_NAME_10=ten
###############################################################################
# Shouldn't need to modify directives below here...
RewriteEngine on
Options +FollowSymLinks
# -----------------------------------------------------------------------------
# Read each URL parameter (if any) and store in corresponding env var
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_01} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_01:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_02} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_02:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_03} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_03:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_04} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_04:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_05} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_05:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_06} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_06:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_07} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_07:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_08} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_08:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_09} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_09:%2]
RewriteCond %{QUERY_STRING}@%{ENV:VAR_NAME_10} (?:^|&)([\w-]+)=([^&@]+).*@\1
RewriteRule ^ - [E=VAR_VALUE_10:%2]
# -----------------------------------------------------------------------------
# Construct new query string
# Only with URL parameters that are not empty
RewriteCond %{ENV:VAR_VALUE_01} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:VAR_NAME_01}=%{ENV:VAR_VALUE_01}]
RewriteCond %{ENV:VAR_VALUE_02} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_02}=%{ENV:VAR_VALUE_02}]
RewriteCond %{ENV:VAR_VALUE_03} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_03}=%{ENV:VAR_VALUE_03}]
RewriteCond %{ENV:VAR_VALUE_04} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_04}=%{ENV:VAR_VALUE_04}]
RewriteCond %{ENV:VAR_VALUE_05} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_05}=%{ENV:VAR_VALUE_05}]
RewriteCond %{ENV:VAR_VALUE_06} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_06}=%{ENV:VAR_VALUE_06}]
RewriteCond %{ENV:VAR_VALUE_07} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_07}=%{ENV:VAR_VALUE_07}]
RewriteCond %{ENV:VAR_VALUE_08} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_08}=%{ENV:VAR_VALUE_08}]
RewriteCond %{ENV:VAR_VALUE_09} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_09}=%{ENV:VAR_VALUE_09}]
RewriteCond %{ENV:VAR_VALUE_10} .
RewriteRule ^ - [E=NEW_QUERY_STRING:%{ENV:NEW_QUERY_STRING}&%{ENV:VAR_NAME_10}=%{ENV:VAR_VALUE_10}]
# -----------------------------------------------------------------------------
# Trim "&" prefix from the NEW_QUERY_STRING
RewriteCond %{ENV:NEW_QUERY_STRING} ^&(.+)
RewriteRule ^ - [E=NEW_QUERY_STRING:%1]
# Compare with existing QUERY_STRING to determine whether it's in the correct order already
# If different then redirect...
RewriteCond %{QUERY_STRING}@@@%{ENV:NEW_QUERY_STRING} !^(.+)@@@\1
RewriteRule ^ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]
Se você tiver alguma dúvida sobre partes específicas deste script, diga nos comentários ...