4

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

Chris Tonkinson
  • 13,823
  • 14
  • 58
  • 90

1 Answers1

7

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
  • 96,375
  • 17
  • 202
  • 225
  • 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 Tonkinson May 16 '10 at 02:14
  • I suppose, specifically, why is the RewriteCond necessary? Also, how does the QSA help if the subpatterns aren't being captured? – Chris Tonkinson May 16 '10 at 02:22
  • 2
    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 & or ? depending on whether the rewritten url already has a query string or not. NE is not really necessary here but it prevents escaping the rewritten URL. It would be useful if you add /index.php?page=$1,$2; NE prevents the comma from becoming %2C – Artefacto May 16 '10 at 02:24
  • 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 May 16 '10 at 02:35