Jak zmienić kolejność parametrów adresu URL / ciągu zapytania za pomocą Apache htaccess?
Mam kategorie eCommerce z nawigacją aspektową (filtrowanie). Filtrowanie może generować tysiące (przydatnych) adresów URL. Chciałbym zmniejszyć nr. możliwych adresów URL, wyświetlając określoną treść zawsze pod tym samym adresem URL z tą samą kolejnością parametrów ciągu zapytania.
Z punktu widzenia SEO mógłbym użyć tagu kanonicznego, aby logicznie wyeliminować zduplikowane adresy URL, ale z punktu widzenia wydajności znacznie lepiej byłoby rozwiązać to za pomocą RewriteRules.
Przykładowe adresy URL z tą samą zawartością, ale inną kolejnością parametrów:
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
Te adresy URL powinny być przekierowane do adresu URL, w którym parametry zapytania pojawiają się zawsze w tej samej kolejności. na przykład:
https://example.com/category/subcategory/?filter_manuf=grohe&filter_family=bauedge&filter_style=design&filter_warranty=5y
Zauważ, że:
- Mam więcej niż 10 kryteriów filtrowania (parametry zapytania)
 - Kolejność parametrów zmienia się zgodnie z kolejnością wyboru filtrów użytkownika. Mogą pojawiać się w dowolnej kolejności.
 - W adresie URL pojawiają się tylko użyte parametry. Niektóre strony mają jeden lub dwa parametry w adresach URL, inne mają nawet dziesięć lub więcej.
 
Czy masz pomysł, jak to osiągnąć?
Znalazłem coś obiecującego w tym pytaniu, ale nie mogę sprawić, by zadziałało: 
 RewriteCond, aby dopasować parametry ciągu zapytania w dowolnej kolejności
Odpowiedzi
ale z punktu widzenia wydajności znacznie lepiej byłoby rozwiązać to za pomocą RewriteRules.
Z punktu widzenia wydajności znacznie lepiej byłoby rozwiązać ten problem w swojej aplikacji, a nie w .htaccess/ mod_rewrite (tj. RewriteRuleS). Chcesz, aby zawsze były prawidłowe linki do kanonicznego adresu URL.
Z pewnością nie chcesz przekierowywać użytkowników na zewnątrz, gdy stosują filtry w celu „poprawienia” kolejności parametrów adresu URL. Parametry adresu URL powinny być stosowane w „prawidłowych” na początku aplikacji.
Jedynym przypadkiem, w którym korzystne byłoby „przekierowanie” użytkownika, byłoby skorzystanie z niekanonicznego linku strony trzeciej (z innej witryny lub wyszukiwarki) i potrzeba rozwiązania potencjalnych problemów z pozycjonowaniem. Ale nawet wtedy kod poprawiający kolejność parametrów adresu URL powinien być znacznie prostszy (i łatwiejszy w utrzymaniu), jeśli zostanie zaimplementowany jako część logiki aplikacji, a nie .htaccess. Kod, który to robi, .htaccessjest stosunkowo bardziej „złożony” (czytaj: niechlujny, potencjalnie trudniejszy w utrzymaniu, bardziej podatny na błędy itp.)
Jest to jednak interesujący problem i może zaistnieć sytuacja, w której preferowane (lub konieczne) jest zakodowanie tego w .htaccess(lub konfiguracji serwera Apache), gdy nie można tego łatwo zrobić w swojej aplikacji.
Rozwiązanie przy użyciu mod_rewrite w .htaccess(lub konfiguracji serwera)
 
     (Jednak zwróć uwagę na powyższe komentarze - może to nie być to, co powinieneś robić.)
Jest to dość ogólne rozwiązanie, które działa w .htaccess(lub w konfiguracji serwera). W obecnej postaci działa na dowolnej ścieżce URL. Aby działał na pojedynczej ścieżce URL (np. Tak /category/subcategory/jak podano w pytaniu), zmodyfikuj wzorzec w końcowej RewriteRuledyrektywie. Na przykład:
RewriteRule ^category/subcategory/$ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]
 
     Możesz też napisać wyjątek u góry, aby pominąć te reguły dla niektórych adresów URL, jeśli chcesz zastosować je do grupy adresów URL, a nie do innych. Może to być bardziej optymalne, ponieważ pozwala uniknąć niepotrzebnego przetwarzania ciągu zapytania.
Ten blok kodu musiałby znajdować się blisko początku .htaccesspliku. (Porządek ma znaczenie.)
Ten kod ma tę dodatkową „zaletę”, że „oczyszcza” również ciąg zapytania, usuwając wszelkie niezdefiniowane parametry adresu URL (u góry skryptu).
Ponieważ nietrywialne jest „proste” określenie, czy oryginalne parametry adresu URL są już we właściwej kolejności, skrypt przechodzi przez proces tworzenia nowego ciągu zapytania z parametrami adresu URL we właściwej kolejności, a następnie porównuje go z oryginalnym zapytaniem ciąg znaków w celu określenia, czy przekierowanie jest konieczne.
Kryteria:
- Maksymalnie 10 parametrów adresu URL
 - Dowolna liczba parametrów adresu URL może pojawić się w dowolnej kolejności
 - Nie należy uwzględniać pustych parametrów adresu URL
 - W parametrach adresu URL rozróżniana jest wielkość liter
 - Działa dla każdej ścieżki URL
 - Nazwy parametrów URL pasuje do wyrażenia regularnego 
[\w-]+(tj.a-z,A-Z,0-9,_I-) - Wartości parametrów adresu URL nie mogą zawierać 
@(chyba że są zakodowane) @@@nie może pojawić się w żadnym miejscu w ciągu zapytania
Wystarczy zdefiniować nazwy parametrów adresu URL na górze skryptu, w takiej kolejności, w jakiej mają być. Są one przechowywane w zmiennych środowiskowych VAR_NAME_01, VAR_NAME_02itp Pozostała część skryptu powinien działać w stanie niezmienionym, chyba że:
- musisz dodać więcej parametrów adresu URL
 - LUB, zmień znak używany wewnętrznie do oddzielania sekcji w dopasowywaniu wzorca (obecnie „ 
@”). - LUB, ogranicz kod do określonej ścieżki URL.
 
Scenariusz:
# 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]
 
     Jeśli masz jakieś pytania dotyczące konkretnych części tego skryptu, napisz w komentarzach ...