I want to redirect each link with a query string to a specific address by appending the string. I have the following in my WordPress .htaccess
:
RewriteEngine On
RewriteCond %{QUERY_STRING} catid=([0-9]+) [NC]
RewriteRule (.*) catid%1? [R=301,L]
When a user hits example.com/?catid=10
, they are successfully redirected to example.com/catid10
, which is what I want.
However, when they go a directory deeper (example.com/category/?catid=10
), they are not redirected to example.com/category/catid10
.
I have been reading manuals but can’t find the answer.
Edit
If this is helpful, this is what WordPress has defined in my htaccess:
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
2
Answers
You just need to add the captured group from
(.*)
to your redirect target using$1
. I’d break it up into a few rules so that you don’t get duplicated slashes. Rather then ending your rewrite targets with a question mark, I would add theQSD
(query string discard) flag to the rule. I would also add starts with (^
) and ends with ($
) to rewrite rule so you always match the whole thing. I also like to start my rules with an optional slash (/?
) so that the rules can be used in both .htaccess and apache conf.Providing
RewriteBase /
is already defined (which it normally is with WordPress and must be if your existing redirect is working) then you can do it like the following with a single rule:The capturing group
(.*?)
is non-greedy so does not consume the optional trailing slash that follows.Requests for the document root do not require
RewriteBase
, but all "deeper" URLs do, since the resulting substitution string will otherwise be a relative URL.The non-capturing
(?:^|&)
prefix on the CondPattern ensures that it only matches the URL parameter namecatid
and notfoocatid
etc.