I have a previous question that was answered very well but requires an amendment and I was unable to reply so have created a new question.
I required a mod_rewrite that made the following:
www.example.com?page=var1&cat=var2&subcat=var3&subsubcat=var4
into this:
www.example.com/var1/var2/var3/var4/
but that also covered the optional use of var2, var3 and var4 so if those variables were empty, it would still work.
The question was answered very well but it requires an amendment to work with different field options for var2, var3 and var4.
The code I have is:
RewriteEngine on
Options +FollowSymlinks -MultiViews
RewriteCond %{QUERY_STRING} !^page= [NC]
RewriteRule ^([^/]+)/?$ /?page=$1 [L]
RewriteCond %{QUERY_STRING} !^page= [NC]
RewriteRule ^([^/]+)/([^/]*)/?$ /?page=$1&cat=$2 [L]
RewriteCond %{QUERY_STRING} !^page= [NC]
RewriteRule ^([^/]+)/([^/]*)/([^/]*)/?$ /?page=$1&cat=$2&subcat=$3 [L]
RewriteCond %{QUERY_STRING} !^page= [NC]
RewriteRule ^([^/]+)/([^/]*)/([^/]*)/([^/]*)/?$ /?page=$1&cat=$2&subcat=$3&subsubcat=$4 [L]
This works but I need it to be able to make an if-or-else for the choice of what field is being used for what variable and to tell the difference.
For example, if we have the following two strings normally, it is easy to distinguish what field goes for what variable:
www.example.com?page=var1&cat=var2&subcat=var3&subsubcat=var4
www.example.com?othervar1=var1&othervar2=var2&othervar3=var3&othervar4=var4
but for this string, it requires the ability to distinguish what field the variable is for:
www.example.com/var1/var2/var3/var4/
I need the mod_rewrite to choose which is being used.
As well as this, when I actually go to a folder that does exist, it does work correctly. For example, if I go to a folder called "test", which is an actual folder:
www.example.com/test/
it uses it as a variable for the "page" field. If I use the following without the end forward slash:
www.example.com/test
it outputs the following into the URL:
www.example.com/test/?page=test
I need it to work for folders that exist as normal also.
Please can someone tell me how this can be done? I would appreciate any help in resolving this issue.
Also, can someone tell me what the "-MultiViews" bit means at the beginning as I have not come across this before?
Thank you.
OK first the MultiViews options: As per Apache manual:
MultiViews
Content negotiated "MultiViews" are allowed using mod_negotiation.
In short if you have a file called foo.html
and if browser requests http://example.com/foo
then Apache automatically finds and appends extension and serves foo.html
to browser rather than throwing 404. This behavior causes many Rewrite rules to fail hence I disabled it at the start in my answer to your previous question.
Now to exclude real directories from being handled by rewrite rules we'll need an additional condition like this: RewriteCond %{REQUEST_FILENAME} !-d
To support multiple pretty URL schemes:
You have few options here. Please tell me which one you would like to have and I will provide rules for that.
Option 1: Have both var name
and var value
in your URL like this:
www.example.com/page/var1/cat/var2/subcat/var3/subsubcat/var4
OR
www.example.com/othervar1/var1/othervar2/var2/othervar3/var3/othervar4/var4
This one gives you maximum flexibility and is very easy to handle in Rewrite rules if you are willing to go to this route. For this option Rewrite rules will need to be written only once and you will be fine for future changes as long # of variables don't change
Option 2: Have a difference start for each scheme. For ex:
www.example.com/handler1/var1/var2/var3/var4
OR
www.example.com/handler2/var1/var2/var3/var4
This one is gives you shorter URL but doesn't provide flexibility like previous option. But this one is also very easy to handle in Rewrite rules. However for this option Rewrite rules will need to be written for every combination
So I would recommend option 1 and would be happy to prepare a .htaccess for you if you like this option too.
.htaccess file for option 2
Options +FollowSymlinks -MultiViews
RewriteEngine on
# 404 handler
ErrorDocument 404 /notFound.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^handler1/([^/]+)/?$ /?page=$1 [NC,QSA,L]
RewriteRule ^handler1/([^/]+)/([^/]+)/?$ /?page=$1&cat=$2 [NC,QSA,L]
RewriteRule ^handler1/([^/]+)/([^/]*)/([^/]*)/?$ /?page=$1&cat=$2&subcat=$3 [NC,QSA,L]
RewriteRule ^handler1/([^/]+)/([^/]*)/([^/]*)/([^/]*)/?$ /?page=$1&cat=$2&subcat=$3subsubcat=$4 [NC,QSA,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^handler2/([^/]+)/?$ /?othervar1=$1 [NC,QSA,L]
RewriteRule ^handler2/([^/]+)/([^/]+)/?$ /?othervar1=$1&othervar2=$2 [NC,QSA,L]
RewriteRule ^handler2/([^/]+)/([^/]*)/([^/]*)/?$ /?othervar1=$1&othervar2=$2&othervar3=$3 [NC,QSA,L]
RewriteRule ^handler2/([^/]+)/([^/]*)/([^/]*)/([^/]*)/?$ /?othervar1=$1&othervar2=$2&othervar3=$3othervar4=$4 [NC,QSA,L]
.htaccess file for option 1
Options +FollowSymlinks -MultiViews
RewriteEngine on
# 404 handler
ErrorDocument 404 /notFound.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)(/.*)?$ $3?$1=$2 [N,QSA,DPI]
RewriteRule ^(/[^/]+|[^/]+/|/?)$ /index.php [L,QSA,DPI]
Using these rules a URL of http://localhost/n1/v1/n2/v2/n3/v3/n4/v4
will be INTERNALLY redirected to http://localhost/?n4=v4&n3=v3&n2=v2&n1=v1
treating each pair of URL segments separated by /
as a name-value
pair for QUERY_STRING. BUT keep in mind if URI doesn't have even number of segments eg: http://localhost/n1/v1/n2/
then it will be redirected to http://localhost/?n1=v1
, discarding extra n2.