Loading...

Knowledge Base

How to Fix Issues with PHP Redirects

Problem

The redirection of www.yourdomain.com/default.html or index.html to http://www.yourdomain.com/index.php?act=whatever redirects it to http://www.yourdomain.com/index.php%3fact=whatever. In other words, why is "?" replaced with "%3f" (or anything else) in the address line? Why is your php redirect not working?

The solution below will show how to fix PHP redirect issues using Apache's mod_rewrite module. The mod_rewrite module is a tool that allows you to manipulate URLs using an unlimited number of rules. You can attach an unlimited number of rule conditions to each rule. This allows you to rewrite URLs by considering server variables, HTTP headers, environment variables, or time stamps.

Solution

To fix the php redirect problem, you can use the mod_rewrite module to redirect a URL to another URL, transform long URLs into short ones, redirect missing pages, and more.

Begin rewriting:

# time to get dynamic, see..
rewriterule ^(.*).html $1.php

Whenever you use mod_rewrite, you need only to do this once per .htaccess file:

Options +SymlinksIfOwnerMatches
RewriteEngine on

Before any ReWrite rules, +FollowSymLinks must be enabled for any rules to work. This is a security requirement of the rewrite engine. Usually, it is enabled in the root, and you should not have to add it.

The following line switches on the rewrite engine for that folder. If this directive is in your main .htaccess file, then the ReWrite engine is theoretically enabled for your entire site. It is wise always to add that line before you write any redirections. While some of the directives on this page may appear split into two lines, in your .htaccess file, they must exist entirely on one line.

Note: For instructions on how to do a PHP header redirect and best practices for using php header redirects, check out the article: How to Code a PHP Redirect - PHP Header Redirect.



Simple Rewriting

Apache scans all incoming URL requests, checks for matches in your .htaccess file, and rewrites those matching URLs to whatever you specify. For example:

#all requests to whatever.html will be sent to whatever.php:
Options +SymlinksIfOwnerMatches
RewriteEngine on
RewriteRule ^(.*).html $1.php [nc]

This can be helpful for anyone updating a site from static HTML (you could use .html or .htm(.*)) to dynamic PHP pages, where requests to the old pages are automatically rewritten to your new URLs. Visitors and search engines can access your content either way. Moreover, this enables you to split PHP code and its included HTML structures into two separate files, making editing and updating easy. The [nc] part at the end means "No Case" or "case-insensitive".

Users can link to whatever.html or whatever.php, but they always get whatever.php in their browser, which works even if whatever.html doesn't exist.

It can be tricky. Visitors will still have whatever.html in their browser address bar and will still keep bookmarking your old .html URLs. This is a php redirect loop. Search engines will also keep on indexing your links as .htm. Some have even argued that serving up the same content from two different places could have you penalized by search engines. This may or may not bother you, but if it does, mod_rewrite can help:

# this will do a "real" http redirection:
Options +SymlinksIfOwnerMatches
rewriteengine on
rewriterule ^(.+).htm$ http://yourdomain.org/$1.php [r=301,nc]

This time, we instruct mod_rewrite to send a proper HTTP (permanently moved) redirection, also known as a 301 redirect. The user's browser is physically redirected to a new URL, and whatever.php appears in their browser's address bar, search engines and other entities will automatically update their links to the .php versions.

Complex Rewriting

You may have noticed that the above examples use a regular expression to match variables. That means it matches the part inside (.+) and uses it to construct "$1" in the new URL. In other words, (.+) = $1, you could have multiple (.+) parts, and for each, mod_rewrite automatically creates a matching $1, $2, $3, etc., in your target URL. For example:

# a more complex rewrite rule:
Options +SymlinksIfOwnerMatches
RewriteEngine on
RewriteRule ^files/(.+)/(.+).zip download.php?section=$1&file=$2 [nc]

This would allow you to present a link as:

http://mysite/files/games/hoopy.zip

and in the background, have that translated to:

http://mysite/download.php?section=games&file=hoopy

which some scripts could process. Many search engines simply do not follow our ?generated=links. So, if you create generating pages, this is useful. Google will handle a good few parameters in your URL without any problems. However, other search engines will not.

Presenting links as/standard/paths means you're less likely to get users making typos in typed URLs.

#an even more complex rewrite rule:
Options +SymlinksIfOwnerMatches
RewriteEngine on
RewriteRule ^blog/([0-9]+)-([a-z]+) http://yourdomain.org/blog/index.php?archive=$1-$2 [nc]

Using the code above would enable anyone to access blog archives by doing:

http://yourdomain.org/blog/2003-nov

in their browser and have it automatically transformed server-side into:

http://yourdomain.org/blog/index.php?archive=2003-nov

which yourdomainblog would understand. It's easy to see that you can perform some URL manipulations with a basic understanding of POSIX regular expression.

Shorten URLs

One common use of mod_rewrite is to shorten URLs. Shorter URLs are easier to remember and easier to type. For example:

# beware the regular expression:
Options +SymlinksIfOwnerMatches
RewriteEngine On
RewriteRule ^grab(.*) /public/files/download/download.php$1

This rule would transform the user's URL server-side:

http://mysite/grab?file=my.zip

into:

http://mysite/public/files/download/download.php?file=my.zip

With this technique, you can move /public/files/download/ to anywhere else on your site, and all the old links still work fine. Just change your .htaccess file to reflect the new location. Edit one line, and you are done.

http://yourdomain.org/img/hotlink.png [nc]

You may see the last line broken into two, but it's all one line (all the directives on this page are). So, take a look at what it does.

We begin by enabling the rewrite engine, as always.

The first RewriteCond line allows direct requests (not from other pages - an "empty referrer") to pass unmolested. The next line means if the browser did send a referrer header and the word "yourdomain" is not in the domain part of it, then DO rewrite this request.

The final RewriteRule line instructs mod_rewrite to rewrite all matched requests (anything without "yourdomain" in its referrer), asking for gifs, jpegs, or pngs to an alternative image.

httpd.conf

Remember, if you put these rules in the main server conf file (usually httpd.conf) rather than a .htaccess file, you'll need to use ^/... ... instead of ^... ... at the beginning of the RewriteRule line, in other words, add a slash. But since httpd.conf is restricted to access, this does not apply at Bluehost.

Inheritance

If you are creating rules in the subfolders of your site, please read below.

Note that rules in top folders apply to all the folders inside those folders. We call this "inheritance." Usually, this works. However, if you start creating other rules inside subfolders, you will obliterate the rules already applying to that folder due to inheritance or descendency if you prefer just the ones applying to that subfolder. For example:

Let's say you have a rule in your main /.htaccess that redirects requests for files ending .html to their .php equivalent, just like the example earlier. Now, if you need to add some rewrite rules to your /osx/.htaccess file, the .html >> .php redirection will no longer work for the /osx/ subfolder. You must reinsert it but with a crucial difference.

# this works fine, site-wide, in my main .htaccess file
# main (top-level) .htaccess file..
# requests to file.html goto file.php
Options +SymlinksIfOwnerMatches
rewriteengine on
rewriterule ^(.*).htm$ http://yourdomain.org/$1.php [r=301,nc]

Below is the updated /osx/. htaccess file, with the .html >> .php redirection rule reinserted, but you will need to reinsert the rules for it to work in this subfolder:

# /osx/.htaccess file..
Options +SymlinksIfOwnerMatches
rewriteengine on
rewriterule some rule that I need here
rewriterule some other rule I need here
rewriterule ^(.*).htm$ http://yourdomain.org/osx/$1.php [r=301,nc]

Spot the difference in the subfolder rule. You must add the current path to the new rule. Now it works again. If you remember this, you can go replicating rewrite rules all everywhere.

Summary

Mod_rewrite allows you to send browsers from anywhere to anywhere. Moreover, you can create rules on the requested URL and on the IP address, browser agent (send old browsers to different pages, for instance), and even the time of day.

The ins and outs of mod_rewrite syntax are topics for a much longer document than this. You can try more advanced rewriting rules. Please check out the Apache documentation for more information. If you are running some *nix operating system (if you have Apache installed on any operating system), there will likely be a copy of the Apache manual on your machine. Check out these excellent mod_rewriting guides for syntax bits.

http://www.ilovejackdaniels.com/apache/mod_rewrite-cheat-sheet/
http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html
http://httpd.apache.org/docs/1.3/misc/rewriteguide.html
http://forum.modrewrite.com/

If you need further assistance, feel free to contact us via Chat or Phone:

  • Chat Support - While on our website, you should see a CHAT bubble in the bottom right-hand corner of the page. Click anywhere on the bubble to begin a chat session.
  • Phone Support -
    • US: 888-401-4678
    • International: +1 801-765-9400

You may also refer to our Knowledge Base articles to help answer common questions and guide you through various setup, configuration, and troubleshooting steps.

Did you find this article helpful?

 
* Your feedback is too short

Loading...