但从性能的角度来看,用RewriteRules来解决会好得多。
From a 表现从角度来看,最好在您的应用程序中解决这个问题,而不是.htaccess
/mod_rewrite(即。RewriteRule
s)。您希望始终正确链接到规范 URL。
您当然不希望在用户应用过滤器以“更正”URL 参数顺序时从外部重定向用户。您的应用程序首先应“正确”应用 URL 参数。
“重定向”用户唯一有益的情况是,如果他们点击了第三方非规范链接(来自其他网站或搜索引擎),并且您需要解决潜在的 SEO 问题。但即便如此,如果将其作为应用程序逻辑的一部分来实现,那么纠正 URL 参数顺序的代码应该会简单得多(并且更容易维护),而不是.htaccess
。执行此操作的代码在.htaccess
相对更“复杂”(阅读:混乱,可能更难维护,更容易出错,等等)
然而,这是一个有趣的问题,有时最好(或有必要)将其编码为.htaccess
(或 Apache 服务器配置)当您无法在应用程序中轻松执行此操作时。
使用 mod_rewrite 的解决方案.htaccess
(或服务器配置)
(However, note the comments above - this may not be what you should be doing.)
这是一个相当通用的解决方案,适用于.htaccess
(或服务器配置)。就目前情况而言,它适用于anyURL 路径。使其在单个 URL 路径上工作(例如/category/subcategory/
,如问题中所述)然后修改pattern在决赛中RewriteRule
指示。例如:
RewriteRule ^category/subcategory/$ %{REQUEST_URI}?%{ENV:NEW_QUERY_STRING} [NE,R=302,L]
或者,如果您需要将其应用于一组 URL 而不是其他 URL,则可以在顶部编写一个例外来跳过某些 URL 的这些规则。这可能是更优化的,因为它避免了对查询字符串的任何不必要的处理。
该代码块需要靠近您的顶部.htaccess
文件。 (顺序很重要。)
此代码还有一个额外的“好处”,即它还通过删除任何未定义的 URL 参数(在脚本顶部)来“清理”查询字符串。
由于“简单地”确定原始 URL 参数是否已按正确顺序排列并非易事,因此脚本会使用按正确顺序排列的 URL 参数构建新的查询字符串,然后将其与原始查询进行比较字符串以确定是否需要重定向。
标准:
- 最多 10 个 URL 参数
- 任意数量的 URL 参数可以以任意顺序出现
- 不应包含空 URL 参数
- URL 参数区分大小写
- 适用于任何 URL 路径
- URL 参数名称与正则表达式匹配
[\w-]+
(ie. a-z
, A-Z
, 0-9
, _
and -
)
- URL 参数值不能包含
@
(除非 URL 已编码)
-
@@@
不能出现在查询字符串中的任何位置
您只需在脚本顶部按照您希望的顺序定义 URL 参数名称即可。这些保存在环境变量中VAR_NAME_01
, VAR_NAME_02
等等。脚本的其余部分应保持不变,除非:
- 您需要添加更多 URL 参数
- 或者,更改内部使用的字符来分隔模式匹配中的部分(当前为“
@
").
- 或者,将代码限制为特定的 URL 路径。
Script:
# 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]
如果您对此脚本的特定部分有任何疑问,请在评论中说...