¿Cómo reordenar los parámetros de URL / cadena de consulta usando Apache htaccess?
Tengo categorías de comercio electrónico con navegación por facetas (filtrado). El filtrado puede generar miles de URL (útiles). Me gustaría reducir el nr. de posibles URL mostrando cierto contenido siempre en la misma URL con el mismo orden de parámetros de cadena de consulta.
Desde el punto de vista del SEO, podría usar la etiqueta canónica para eliminar lógicamente las URL duplicadas, pero desde el punto de vista del rendimiento sería mucho mejor resolverlo con RewriteRules.
Ejemplos de URL con el mismo contenido pero diferente orden de parámetros:
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
Estas URL deben redirigirse a una URL en la que los parámetros de consulta aparezcan siempre en el mismo orden. p.ej:
https://example.com/category/subcategory/?filter_manuf=grohe&filter_family=bauedge&filter_style=design&filter_warranty=5y
Tenga en cuenta que:
- Tengo más de 10 criterios de filtrado (parámetros de consulta)
- El orden de los parámetros cambia según el orden de selección del filtro del usuario. Pueden aparecer en cualquier orden.
- Solo los parámetros que se utilizan aparecen en la URL. Algunas páginas tienen uno o dos parámetros en su URL, algunas tienen hasta diez o más.
¿Tienes idea de cómo se puede lograr?
Encontré algo prometedor en esta pregunta, pero no puedo hacer que funcione:
RewriteCond para que coincida con los parámetros de la cadena de consulta en cualquier orden
Respuestas
pero desde el punto de vista del rendimiento sería mucho mejor resolverlo con RewriteRules.
Desde el punto de vista del rendimiento , sería mucho mejor resolver esto en su aplicación, no en .htaccess/ mod_rewrite (es decir, RewriteRules). Desea estar siempre vinculado correctamente a la URL canónica.
Ciertamente, no desea redirigir externamente al usuario, ya que aplica filtros para "corregir" el orden de los parámetros de URL. Los parámetros de URL deben aplicarse en el "correcto" para empezar por su aplicación.
La única vez que sería beneficioso "redirigir" al usuario es si ha seguido un enlace no canónico de un tercero (de otro sitio web o motor de búsqueda) y necesita resolver posibles problemas de SEO. Pero incluso entonces, el código para corregir el orden de los parámetros de URL debería ser mucho más simple (y más fácil de mantener) si se implementa como parte de la lógica de su aplicación, no .htaccess. El código para hacer esto .htaccesses comparativamente más "complejo" (léase: desordenado, potencialmente más difícil de mantener, más propenso a errores, etc.)
Sin embargo, es un problema interesante y puede haber una ocasión en la que sea preferible (o necesario) codificar esto en .htaccess(o en la configuración del servidor Apache) cuando no pueda hacerlo fácilmente en su aplicación.
Solución usando mod_rewrite en .htaccess(o configuración del servidor)
(Sin embargo, tenga en cuenta los comentarios anteriores; es posible que esto no sea lo que debería hacer).
Esta es una solución razonablemente genérica que funciona en .htaccess(o configuración del servidor). Tal como está, funciona en cualquier ruta de URL. Para que funcione en una única ruta de URL (por ejemplo /category/subcategory/, como se indica en la pregunta), modifique el patrón en la RewriteRuledirectiva final . Por ejemplo:
RewriteRule ^category/subcategory/$ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]
O puede escribir una excepción en la parte superior para omitir estas reglas para ciertas URL si necesita aplicarlas a un grupo de URL y no a otras. Esto podría ser más óptimo ya que evita cualquier procesamiento innecesario de la cadena de consulta.
Este bloque de código debería ir cerca de la parte superior de su .htaccessarchivo. (El orden importa).
Este código tiene el "beneficio" agregado de que también "desinfecta" la cadena de consulta al eliminar cualquier parámetro de URL que no esté definido (en la parte superior del script).
Dado que no es trivial determinar "simplemente" si los parámetros de URL originales ya están en el orden correcto, la secuencia de comandos pasa por el proceso de construcción de una nueva cadena de consulta con los parámetros de URL en el orden correcto y luego los compara con la consulta original. cadena para determinar si es necesario un redireccionamiento.
Criterios:
- Hasta 10 parámetros de URL
- Puede aparecer cualquier número de parámetros de URL en cualquier orden
- Los parámetros de URL vacíos no deben incluirse
- Los parámetros de URL distinguen entre mayúsculas y minúsculas
- Funciona para cualquier ruta de URL
- Nombres de los parámetros URL coincide con la expresión regular
[\w-]+(es decir.a-z,A-Z,0-9,_Y-) - Los valores de los parámetros de URL no pueden contener
@(a menos que estén codificados en URL) @@@no puede aparecer en ninguna parte de la cadena de consulta
Simplemente debe definir los nombres de los parámetros de la URL en la parte superior del script, en el orden que desee. Estos se llevan a cabo en las variables de entorno VAR_NAME_01, VAR_NAME_02etc. El resto de la secuencia de comandos debería funcionar sin variación alguna salvo:
- necesitas agregar más parámetros de URL
- O, cambie el carácter utilizado internamente para delimitar secciones en la coincidencia de patrones (actualmente "
@"). - O, limite el código a una ruta URL específica.
Guión:
# 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]
Si tiene alguna consulta sobre partes específicas de este script, solo diga en los comentarios ...