Reputation: 78
i have php page with one or more get variables and variables order can be different for different process
www.lorem.com/ipsum.php?var1=aaa&var2=bbb&var3=ccc
www.lorem.com/ipsum.php?var2=bbb&var3=ccc
www.lorem.com/ipsum.php?var2=bbb&var3=ccc&var1=aaa
i want to rewrite part of url for all kind of process
www.lorem.com/ipsum/v1_aaa-v2_bbb-v3_ccc
www.lorem.com/ipsum/v2_bbb-v3_ccc
www.lorem.com/ipsum/v2_bbb-v3_ccc-v1_aaa
How can i write Rewrite Rule for change var1=aaa part to v1_aaa and & to - also ipsum.php? to ipsum/
i wanna learn how to write.
Upvotes: 1
Views: 81
Reputation: 20737
What you are trying to do is not really simple. What you are trying to do can be split into two parts:
.php
extension from a pagekey-value
. I used the -
character as a delimiterWhen rewriting urls to a seo-friendly url, you'll always need to keep in mind that you need to be able to rewrite it back to the original url internally, or otherwise no page can be displayed.
What should be in .htaccess
You would need to do something along the lines of the following .htaccess
. I'll try to explain some of it below the code.
#External redirect
RewriteCond %{THE_REQUEST} \.php
RewriteRule ^(.*)\.php$ $1 [E=redirflag:1]
RewriteCond %{ENV:redirflag} =1
RewriteCond %{QUERY_STRING} ^([^=]+)=([^&]+)(&(.*)|)$
RewriteRule ^(.*)/(ipsum|otherpage|test)(/.*)?$ $1/$2$3/%1-%2?%4 [E=redirflag:1,N]
RewriteCond %{ENV:redirflag} =1
RewriteRule ^(.*)$ /$1 [R,L,E=!redirflag]
#Internal rewrite
RewriteRule ^(.*)/([^-]+)-(.+)/?$ $1?$2=$3 [QSA,N,DPI]
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ /$1.php [L]
Closer look at external redirect
Let's take a closer look at what happens. The first rule is to remove the .php
extension from an url. We use %{THE_REQUEST}
to make sure that in the external request there is somewhere .php
. If we wouldn't do this, we would create an infinite loop. Because we want to do some other rewrites before redirecting, I set an environment variable (docs). $1
is replaced by the first capture group on the same line.
The second rule is to rewrite all key-value pairs to a /key-value/
addition to the url. It will only work for urls containing ipsum
, otherpage
and test
(not necessarily end on it). The first condition is to check if the flag I set in the first rule is 1
. That means that if the first rule didn't match, I don't match this rule either. Notice I use =1
, which checks if the variable is equal to the string 1
, and doesn't treat is as a regex expression. (docs). The regex in the second condition matches the key in capture group 1, the value in capture group 2 and if more key and values are behind it, matches those in capture group 4. %1
and similar variables in the actual rule will be replaced by the corresponding capture group in the last rewritecondition. The N
flag will keep restarting the .htaccess
from the very beginning until this rule doesn't match anymore.
The third rule will redirect the client to the url we did just rewrite. R
is a temporary redirect. Set this to R=301
when you are happy with all your urls to make it a permanent redirect. E=!redirflag
will delete that environment variable.
Closer look at internal rewrite
The client does a new request to your server with the seo-friendly url. We'll need to internally rewrite that back to an url that is actually useful to the server. As at the end of the url we have (or could have) key-value pairs, so let's start with rewriting those back to key-value pairs in a query string. The QSA
flag appends the current query string to the query string we already had. The N
flag we have already seen. The DPI
flag is "discard path info" and is to prevent duplicate paths appending at the end of the url, resulting in an infinite loop. If this was to be omitted, your server would lock up, the error log would be quite expansive and Apache will eventually crash I believe.
The second rule will only match if the first rule doesn't match anymore. There are no more key-value pairs at the end of the url, so we have ended up at the bit where we removed the php extension in the very beginning. Let's append this again. The condition for this rule is that the uri doesn't already end with .php
. If this condition wouldn't be there, it would keep appending .php
and you'll end up with something like test.php.php.php.php.php
(and we don't want that).
Further reading
First of all, read the documentation of mod_rewrite
. It is quite detailed, and is a great reference guide if you don't understand something in code related to it.
mod_rewrite
uses perl-like regex syntax. If you have trouble understanding what a certain regex means, hold a PREG/PCRE syntax sheet next to it. That should help a lot when trying to understand, or write something. An online preg regex tool can help greatly to see what a certain expression does and doesn't match. Keep in mind that there might be differences in what should and shouldn't be escaped though.
Upvotes: 1