Php – $_GET and URL Rewriting for PHP

friendly-urlPHPurl-rewritingurl-routing

How does URL rewriting affect the $_GET parameter for PHP?

Say I have a URL like http://example.com/index.php?p=contact and I use $_GET['p'] to tell index.php to serve the contact page. If I use a rewrite rule that converts the URL to http://example.com/contact, will $_GET['p'] still work as expected?

If it does, could you elaborate on why it works? If not, what strategies could be used to solve the problem so that the page will work both with and without the rewrite?

Best Answer

I'd amend Grant's answer to "Yes, that will work mostly as expected."

Specifically, mod_rewrite's behavior with regards to existing query strings can be surprising. As an example, let's take the following rule, which converts the URL you supplied:

RewriteRule /contact /index.php?p=contact

This will correctly rewrite /contact to /index.php?p=contact and the page name will be accessible through $_GET['p']. However, if you use this technique with a script that uses parameters other than the page name, it gets slightly trickier. This rule also translates /contact?person=Joe to /index.php?p=contact. The person=Joe parameter disappears entirely! There are two ways to deal with this.

The simplest way is to use the [QSA] ("query string append") flag on your rule, which will place the original query string after the parameters supplied in the rule, translating /contact?person=Joe to /index.php?p=contact&person=Joe:

RewriteRule /contact /index.php?p=contact [QSA]

However, this makes it possible for your p= parameter to get overwritten. Visiting /contact?p=about will get rewritten to /index.php?p=contact&p=about, so $_GET['p'] will return "about" in your script, not "contact". To resolve this, use the QUERY_STRING variable instead:

RewriteRule /contact /index.php?%{QUERY_STRING}&p=contact

This guarantees that $_GET['p'] will always return "contact" when using this rule, regardless of whether your visitors are messing with your URLs. :-)