Using mod_rewrite On Form Parameters

Using mod_rewrite on websites is fairly straightforward and can create some lovely looking URL structures. Instead of having a URL that contains lots of odd looking parameters like this:

http://www.example.com/example.php?parameter1=value1&parameter2=value2

You can use a .htaccess file to rewrite the URL on the server side in order to shorten this to something like this:

http://www.example.com/p-value1

In this occasion the value of parameter2 will always be value2 so we can just include that in the rewrite rule, which would look something like the following. $1 is a back-reference to the first parenthesized value matched in the RewriteRule.

RewriteRule ^p-(.*)$ /example.php?parameter1=$1&parameter2=value2 [L]

Remember to turn ensure that the FollowSynLinks directive is enabled and that the rewrite engine is turned on before starting your rewrite rules. FollowSynLinks should have been enabled by your server administrator, but you can include here just in case they haven't.

Options +FollowSymLinks
RewriteEngine On

You can also make sure that mod_rewrite is actually installed by enclosing all of this in an if statement. This will stop the server throwing an error if you don't have mod_rewrite.

<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
</IfModule>

What PHP sees on the server side is exactly the same as normal so you can retrieve the parameters with a standard $_GET lookup.

However, the default behaviour of forms messes this up. Lets say that we had a search page that we created a rewrite rule so that it read like this:

http://www.example.com/s-value1

This redirects to the page search.php and passes any parameters to that page. The problem here is if we call the same page through a form. Here is an example search form.

<form action="search.php" method="get">
<input type="text" name="q" value="" />
<input type="submit" name="s" value="Search" />
</form></code>

When this is run with the string "test" the URL looks like this.

search.php?q=test&s=Search

This is the default browser behaviour, but it still messes up the nice URL structure created previously. There is a way to fix this. Have a look at the following .htaccess file.

<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
 
RewriteCond %{REQUEST_URI} /search.php$
RewriteCond %{QUERY_STRING} ^q=([A-Za-z0-9\+]+)&s=Search$
RewriteRule ^(.*)$ /s-%1? [R=301,L]
 
RewriteRule ^s-(.*)$ /search.php?q=$1&s=Search&a=1 [L]
</IfModule>

Here we are using the RewriteCond directive which allows us to test for certain conditions. In this case we have two conditions.

RewriteCond %{REQUEST_URI} /search.php$
RewriteCond %{QUERY_STRING} ^q=([A-Za-z0-9\+]+)&s=Search$

The first condition allows us to only run the rule on the page search.php. This stops any annoying confusion if we want to pass a similar query string to a different page. The second condition allows us to test the query string to see if it contains the parameters we are looking for. The %{QUERY_STRING} bit is a reference to the actual query string passed, minus the question mark at the beginning. In this case we want to trap the parameter q with any value and the parameter s with the value of Search. The dollar sign at the end is very important, but I'll come back to that.

The first rewrite rule redirects the page search.php to the URL /s- and whatever the query string was. The %1 is a back-reference to the first parenthesised value matched in the most-recently-matched RewriteCond.

RewriteRule ^(.*)$ /s-%1? [R=301,L]

We then also need to include a rewrite rule that will recognise the new URL and act on it. However, want we don't want to do is confuse the server and put it into an endless loop, which is quite easy since we are redirecting from search.php to search.php. So what we do is include the parameter "a" at the end of our rewrite rule with the value of 1.

RewriteRule ^s-(.*)$ /search.php?q=$1&s=Search&a=1 [L]

Going back to the second rewrite condition above we included a dollar sign at the end of the rule. This meant that the string had to end there, so if we include anything else after the end of the query string the rewrite condition will return false. So although we don't actually use the a in our script it is needed there to stop the server going into an infinite loop of redirects.

For more information on mod_rewrite and other .htaccess examples have a look at the excellent tutorial at Ask Apache.

Comments

i love this site.
Permalink
You have built a good website
Permalink
keep up the good work!(
Permalink
Awesome, I've been looking for days for this kind of code. Thanks for sharing!
Permalink
Thank you for this sharing. It's really good code. But I still can't use this code, cause I need to 3 variables. something liek index.php?lang=en(any language)&table=2(any_number)&keyword=something need to forward something like www.domain.com/en/2/search/something/Maybe you can help me? how to send all this variables. Is it possible? Regards, Mark
Permalink
<form> <input type=hidden name=language> <input type=hidden name=table> <input type=hidden name=keyword> </form> form look like this one.
Permalink
OK, so your form will produce the following url:
index.php?lang=en&table=2&keyword=something
So you need to make sure that the rewrite rules pick the information up and present it in the correct place.
RewriteCond %{REQUEST_URI} /index.php$
RewriteCond %{QUERY_STRING} ^lang=([A-Za-z]+)&table=([0-9]+)keyword=([A-Za-z0-9\+]+)&s=Search$
RewriteRule ^(.*)$ /%1/%2/%3? [R=301,L]
 
RewriteRule ^/([A-Za-z]+)/([0-9]+)/(.*)$ /index.php?lang=$1&table=$2&keyword=$3&s=Search&a=1 [L]
Hopefully you shouldn't need to tweak this too much to get it to run, but I haven't tested it so don't think that this is the definitive solution. Let me know how you get on.
Name
Philip Norton
Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
5 + 10 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.