views:

38

answers:

1

I have a PHP-based web app that I'm trying to apply Apache's mod_rewrite to.

Original URLs are of the form:
http://example.com/index.php?page=home&x=5

And I'd like to transform these into:
http://example.com/home?x=5

Note that while rewriting the page name, I'm also effectively "moving" the question mark. When I try to do this, Apache happily performs this translation:

RewriteRule ^/([a-z]+)\?(.+)$ /index.php?page=$1&$2  [NC,L]

But it messes up the $_GET variables in PHP. For example, a call to http://example.com/home?x=88 yields only one $_GET variable (page => home). Where did x => 88 go? However, when I change my rule to use an ampersand rather than a question mark:

RewriteRule ^/([a-z]+)&(.+)$ /index.php?page=$1&$2  [NC,L]

a call like http://example.com/home&x=88 will work just as I'd expect it to (i.e. both the page and x $_GET variables are set appropriately).

The difference is minimal I know, but I'd like my URL variables to "start" with a question mark, if it's possible. I'm sure this reflects my own misunderstanding of how mod_rewrite redirects interact with PHP, but it seems like I should be able to do this (one way or another).

Thanks in advance!
Cheers,
-Chris

+3  A: 

Try this:.

RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^/([a-z]+)(?:$|\?(?:.+)) /index.php?page=$1 [NC,L,B,QSA,NE]

B escapes the backreference (shouldn't be necessary since it is matching [a-z]+, but in case you want to extend it later, it might be useful).

EDIT: added RewriteCond. EDIT 2: QSA takes care of adding the ampersand.

Artefacto
Thanks - worked like a charm - but can you explain why? I'm no novice to PCRE (your regex is perfectly intelligible), but the semantics of how this is producing the desired result leaves me confused.
Chris
I suppose, specifically, why is the RewriteCond necessary? Also, how does the QSA help if the subpatterns aren't being captured?
Chris
Th important flag is QSA (query string append); it appends the query string (the part after ?) of the original request to the rewritten request. It also takes take of adding either NE prevents the comma from becoming %2C
Artefacto
Okay, that makes a little more sense; thanks!
Chris
The RewriteCond is not really necessary. However, if you remove the L flag or impose an HTTP forward and allow the captured group to contain dots, you could find yourself in an infinite loop. So feel free to remove it.
Artefacto
Good point, I was wondering if that was necessary.
Chris