Cyclone
Cyclone

Reputation: 18295

.htaccess and $_GET rewrite

I am having an annoying issue. I have a script which uses the $_GET feature of php to get a variable from the url of the page. However, I need to know how to, first and foremost, make my page url go from

http://www.example.com/dir/dir2/page.php?value=something&anothervalue=somethingelse

to

http://www.example.com/something/dir2/somethingelse/page.php

This is confusing for me.

Now, here is the tough part: How do I $_GET the values of value and anothervalue while leaving any other url values intact at the end of page.php? Also, if a user visits http://www.example.com/something/dir2/somethingelse/page.php they will be shown the content for http://www.example.com/dir/dir2/page.php?value=something&anothervalue=somethingelse , and vice versa, right?

This is very important to the operation of my site, thanks for helping in advance! I don't know anything about .htaccess at all but I do know that it is possible to do this.

To clarify, doing this very confusing thing will actually make things much simpler in the long run as it will require much less recoding and will provide cleaner URLS.

Upvotes: 0

Views: 2660

Answers (3)

Gumbo
Gumbo

Reputation: 655269

This rule should do it:

RewriteCond %{REQUEST_URI} !^/dir/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/(.*) dir/$2/$4?value=$1&anothervalue=$3 [L,QSA]

It will rewrite requests of /something/dir2/somethingelse/page.php internally to /dir/dir2/page.php?value=something&anothervalue=somethingelse.

But that wouldn’t prevent from requesting the latter directly but just allowing an alias.

Redirecting requests of /dir/dir2/page.php?value=something&anothervalue=somethingelse externally to /something/dir2/somethingelse/page.php is also possible with mod_rewrite but requires a little more complex rule since the URL parameters can have an arbitrary order:

RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{QUERY_STRING} ^(([^&]*&)*)value=([^&]+)&?([^&].*)?$
RewriteCond %3&%1%4 ^([^&]+)&(([^&]*&)*)anothervalue=([^&]+)&?([^&].*)?$
RewriteRule ^dir/([^/]+)/(.*) /%1/$1/%4/$2?%2%5 [L,R=301]

As you see, that’s not really nice. A better solution would be to check with PHP what URL has been requested (see $_SERVER['REQUEST_URI']) and do the redirect with PHP (see header function).

Upvotes: 2

phenry
phenry

Reputation: 2057

For the specific rewrite you pose above, something like this should work:

RewriteEngine On
RewriteRule ^/(.*)/(.*)/(.*)/(.*)\.php$ /dir/\2/\4.php?value=\1&anothervalue=\3 [L]

...although in practice I wouldn't recommend using the dot token as shown, as it will match paths with extra levels in them and screw up the rewrite. Replacing each dot with [^/] might work, although I would want someone who's better at regexes than I am to take a look and determine whether there are any pitfalls there as well. Anyway, the important point is that regular expressions can be very complex as well as very powerful, and a full explanation of them is way beyond the scope of this answer. Try spending some time at http://www.regular-expressions.info for a general tutorial.

Also, if a user visits http://www.example.com/something/dir2/somethingelse/page.php they will be shown the content for http://www.example.com/dir/dir2/page.php?value=something&anothervalue=somethingelse , and vice versa, right?

No; it only works one way. To do it both ways you would need two RewriteRules.

I'm not sure I understand your question about $_GET. $_GET is an array that is filled with key/value pairs for each of the parameters in the URL; you may use as many or as few of them as you wish. It's not destructive--using it doesn't alter the parameters of the URL string.

Upvotes: 1

chaos
chaos

Reputation: 124297

You're right, it is possible to do that. Others may disagree, but I tend to think that the appropriate thing at the point you're at is to refer you to the documentation for mod_rewrite. If you're going to be maintaining that complex of a set of rewrites, you're going to need to learn about it sooner or later, so it may as well be now.

Upvotes: 2

Related Questions