.htaccess RewriteRule捕获搜索串返回空值及404问题排查
问题1:访问http://website.com/order?product=L0231-03868时product值为空
核心原因:RewriteRule的匹配范围仅针对URL的路径部分,不包含问号后的查询字符串。你写的^order(.*)$只会匹配/order这个路径,?product=xxx属于查询字符串,不会被规则里的(.*)捕获,所以$1是空值,最终重写后的URL是/index.php?p=order&product=,自然$_GET里的product为空。
另外,默认情况下如果RewriteRule的目标URL包含查询字符串,原请求的查询字符串会被替换而非追加,所以原有的product=L0231-03868直接被覆盖了。
问题2:修改规则为RewriteRule ^order\?(.*)$ /index.php?p=order&product=$1 [L,NC]出现404
还是因为RewriteRule的匹配范围:URL的路径部分不会包含问号(问号是路径与查询字符串的分隔符),这个规则根本匹配不到任何请求,所以返回404。
解决方案
根据你的需求,分两种场景处理:
场景1:直接保留原查询字符串的所有参数
如果只是想把/order?product=xxx重写到/index.php?p=order,同时保留原查询字符串的参数,加上QSA(Query String Append)标记即可:
RewriteRule ^order$ /index.php?p=order [L,NC,QSA]
QSA的作用是将原请求的查询字符串追加到目标URL的查询字符串后,这样访问/order?product=L0231-03868时,最终URL是/index.php?p=order&product=L0231-03868,$_GET就能正确获取product的值。
场景2:精准捕获查询字符串中的product参数
如果需要严格匹配仅含product参数的请求,用RewriteCond匹配查询字符串:
# 匹配查询字符串以product=开头的请求 RewriteCond %{QUERY_STRING} ^product=(.*)$ # 匹配路径为/order的请求 RewriteRule ^order$ /index.php?p=order&product=%1 [L,NC]
这里%1对应RewriteCond中捕获的分组内容(即product的值),能精准传递参数。
补充:同时支持路径式参数(如/order/L0231-03868)和查询字符串参数
可以结合两种规则:
# 处理路径式参数:/order/xxx RewriteRule ^order/(.*)$ /index.php?p=order&product=$1 [L,NC] # 处理查询字符串参数:/order?product=xxx RewriteRule ^order$ /index.php?p=order [L,NC,QSA]
内容的提问来源于stack exchange,提问作者Moseleyi

